/* =============================================================================
   The customer account page.

   DESIGN PLAN, so the next person changing this knows what was chosen and why.

   PALETTE — the site's own tokens, imported from /styles.css, and no new
   identity. --bg #08090e, --accent #10b981, --text-2 #6b7085, --border. This
   page is one door into ezcoins.shop, not a product of its own, and the fastest
   way to make a signed-in area feel like a phishing page is to give it a look
   the marketing site does not have. The page-local additions are the gate's own
   room and Discord blurple on exactly one button, for the same reason the admin
   gate uses it — a control that hands your account to a third party should look
   like that third party before you click it.

   TYPE — Inter, the brand face, in three roles: the standing figure at 900 and
   -0.04em, eyebrows at 11px/700/0.16em uppercase in --text-2, and every figure
   set `tabular-nums` so the ladder's thresholds and the order amounts form real
   columns instead of ragged ones. Deliberately no second family. A display
   serif here would be this page's signature rather than EZCoins'.

   LAYOUT — a two-column shelf at >=920px: the ladder is a sticky left rail, the
   order history scrolls beside it. Below that, one column, ladder first,
   because the tier is what a returning customer opens this page to look at.

   SIGNATURE — the loyalty ladder, drawn as a ladder rather than a progress bar.
   Rungs stack bottom to top carrying their real Discord role names; earned ones
   are solid, unearned ones hollow; and the rail is painted to the customer's
   true position BETWEEN two rungs, not snapped to the last one reached. The
   standing figure sits at the foot of the rail rather than in a stat tile above
   it, so the number and the climb read as one object: this is where you are
   standing, and that is what is above you.

   The one risk taken: even rung spacing on a scale that is anything but even.
   The live ladder is the guild's own coin roles, 200M+ through 100B+ —
   SEVENTEEN rungs from 200 to 100,000. See ladderFill() in lib/account-view.js:
   on a true scale the bottom eight rungs collapse into the first 7% of the
   rail, which is where nearly every customer stands. Rungs on a ladder are
   evenly spaced; the names beside them carry the cost.

   Every class here is prefixed `c-`. styles.css already claims .stat, .card and
   .container, and this page loads it for the tokens and the buttons.
   ========================================================================== */

:root {
  --c-blurple: #5865F2;
  --c-blurple-hover: #4752c4;
  --c-rail-w: 2px;
  /* The gate's room. --c-scrim is how hard the dark press sits on the photo;
     it is the only knob worth turning if the card ever stops being readable. */
  --c-scrim: 0.52;
  --c-floor: #050609;
  /* The rail lives in a gutter to the left of the panel's text column, and
     the eyebrow, the rungs and the standing figure all share one left edge. */
  --c-gutter: 26px;
}

.light {
  /* Light mode does NOT get the photograph. It is a night sky, and there is no
     amount of washing that turns a night sky into a light background - every
     attempt either leaves a dark page under a pale card, or bleaches the
     aurora out until only a grey smear is left. Light mode gets a clean floor
     and a single soft light instead, which is a deliberate second design
     rather than the first one damaged. */
  --c-glow: rgba(16, 185, 129, 0.10);
  --c-floor: #eef0f6;
}

/* The marketing page hides overflow-x and paints a canvas; neither applies
   here, and this page scrolls normally. */
/* [hidden] is a UA-sheet rule at the lowest specificity, so ANY class rule
   that sets display beats it. .c-gate sets display:grid, so without this the
   sign-in card and the signed-in page render on top of each other the moment
   the page decides which one to show. This is the whole reason the page has one
   visible state instead of two. */
[hidden] { display: none !important; }

body.c-body {
  min-height: 100vh;
  background: var(--bg);
}

/*
   THE SIGNED-IN PAGE HAS NO BACKGROUND. That is the decision, not an omission.

   It carried a fixed layer with two radial glows — emerald in one corner,
   Discord blurple in the other. Same pattern, same verdict as the dot grid on
   the gate: it is what every generated dashboard on the internet looks like,
   and it reads as exactly that.

   The gate can afford atmosphere because it holds ONE object in an empty room.
   This page is full of content — a summary card, a stat row, fifteen order
   rows — and a coloured wash behind all of it is competing with the thing it
   is meant to be showing. Flat --bg, and the cards do the work.
*/
.c-page { position: relative; z-index: 1; }

/* ===== Header ============================================================ */

.c-header {
  display: flex;
  align-items: center;
  gap: 16px;
  max-width: 1120px;
  margin: 0 auto;
  padding: 24px;
}

.c-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text);
}

.c-back .c-accent { color: var(--accent); }
.c-back svg { width: 14px; height: 14px; color: var(--text-2); transition: transform 0.2s; }
.c-back:hover svg { transform: translateX(-3px); }

.c-header-spacer { flex: 1; }

/* On a phone the row does not fit: back link, theme toggle, avatar, name and
   Sign out came to about 460px against 390 of screen, and the button fell off
   the right edge taking the page's horizontal scroll with it.
   The identity chip moves to its own full-width row rather than the name being
   truncated away — knowing WHICH Discord account the page is acting as is the
   reason that chip exists, and a phone is exactly where someone is most likely
   to be signed in as the wrong one. */
@media (max-width: 560px) {
  .c-header {
    flex-wrap: wrap;
    gap: 12px;
    padding: 18px 16px;
  }

  .c-header-spacer { display: none; }
  .c-back { flex: 1 1 auto; }

  .c-whoami {
    flex: 1 1 100%;
    justify-content: space-between;
  }

  .c-whoami-name { max-width: none; }
}

/* The account, as an account. Who this page is acting as, not just that
   somebody is signed in — two of the owner's own Discord accounts differ by a
   single letter, which is the whole reason the admin gate started printing
   this. */
.c-whoami {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 6px 6px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
}

.c-whoami-name {
  font-size: 13px;
  font-weight: 600;
  max-width: 16ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.c-avatar {
  position: relative;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
  background: var(--accent-subtle);
  display: grid;
  place-items: center;
}

.c-avatar-initial {
  font-size: 12px;
  font-weight: 700;
  color: var(--accent);
}

.c-avatar-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ===== Shared section furniture ========================================== */

.c-eyebrow {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-2);
}

.c-panel {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  backdrop-filter: blur(12px);
}

/* Every figure on this page. Without tabular numerals the thresholds beside the
   rungs are ragged, and a column of amounts stops reading as a column. */
.c-num { font-variant-numeric: tabular-nums; }

/* ===== The signed-in page ================================================ */

/*
   LAYOUT. A summary band across the top, history underneath, both full width.

   What this replaced: a sticky left rail carrying a seventeen-rung ladder, with
   the order list squeezed beside it. Three things were wrong with it — you read
   fifteen tiers you have not reached before reaching your own number; the page
   below the order list was empty; and the ladder, which is reference material,
   was the loudest thing on a page about you.
*/
.c-main {
  max-width: 900px;
  margin: 0 auto;
  padding: 8px 24px 96px;
}

.c-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ===== The summary band ================================================== */

.c-summary {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  backdrop-filter: blur(12px);
  overflow: hidden;
}

/* ── Who you are ── */

.c-identity {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 22px 26px;
  border-bottom: 1px solid var(--border);
}

.c-identity-avatar {
  position: relative;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
  background: var(--accent-subtle);
  display: grid;
  place-items: center;
}

.c-identity-avatar .c-avatar-initial { font-size: 17px; font-weight: 700; color: var(--accent); }

.c-identity-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }

.c-identity-name {
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.02em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.c-identity-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* The tier is a thing you HOLD, so it is a badge rather than a line of text.
   Hidden until earned — "no tier yet" is a sentence about an absence, and the
   progress bar below already says what the first one costs. */
.c-tier {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: 999px;
  background: var(--accent-subtle);
  color: var(--accent);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}

.c-since { font-size: 12.5px; color: var(--text-2); }

.c-identity-out { margin-left: auto; flex-shrink: 0; }

/* ── The three figures ── */

.c-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.c-stat {
  padding: 20px 26px;
  border-right: 1px solid var(--border);
}

.c-stat:last-child { border-right: none; }

/* dd before dt in the markup, so the figure leads and the label explains it.
   The default dd indent has to go or every figure sits 40px in. */
.c-stat-value {
  display: block;
  margin: 0;
  font-size: 27px;
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.1;
  color: var(--text);
}

.c-stat-label {
  display: block;
  margin-top: 3px;
  font-size: 12.5px;
  color: var(--text-2);
}

/* ── Progress to the next tier ── */

.c-progress {
  padding: 18px 26px 22px;
  border-top: 1px solid var(--border);
}

.c-progress-ends {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 8px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
}

.c-progress-from { color: var(--accent); }
.c-progress-to { color: var(--text-2); }

.c-progress-track {
  height: 6px;
  border-radius: 999px;
  background: var(--surface-hover);
  overflow: hidden;
}

.c-progress-fill {
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 70%, transparent), var(--accent));
  /* Animated once on load: the bar filling is the page's only motion, and it
     is the one number here that is going somewhere. Width is set inline from
     the ladder's own progress fraction. */
  transition: width 900ms cubic-bezier(0.16, 1, 0.3, 1);
}

.c-progress-note {
  margin-top: 9px;
  font-size: 13px;
  color: var(--text-2);
}

.c-progress-note strong { color: var(--text); font-weight: 600; }

/* ===== History =========================================================== */

.c-history { margin-top: 30px; }

.c-orders-head { padding: 0 2px 12px; }

@media (max-width: 620px) {
  .c-main { padding: 4px 16px 64px; }

  /* Sign out drops to its own full-width row. Kept inline it squeezed the text
     column to about 150px, which wrapped "Customer since May 2026" onto two
     lines and ran the name into the button. */
  .c-identity {
    flex-wrap: wrap;
    padding: 18px;
  }

  .c-identity-text { flex: 1 1 0; }

  .c-identity-out {
    flex: 1 1 100%;
    margin-left: 0;
    justify-content: center;
  }
  /* Three figures at 33% each is about 90px a column on a phone, which is
     narrower than "$5,627.50". Two up, one under. */
  .c-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .c-stat { padding: 16px 18px; border-bottom: 1px solid var(--border); }
  .c-stat:nth-child(2n) { border-right: none; }
  .c-stat:last-child { grid-column: 1 / -1; border-bottom: none; }
  .c-stat-value { font-size: 23px; }
  .c-progress { padding: 16px 18px 20px; }
}

/* ===== Orders ============================================================ */

.c-orders-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 4px 2px 14px;
}

.c-count {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--text-2);
}

/* Two rows in the left column — the kind above the thing — and the date
   spanning both on the right. Written as explicit grid areas rather than as
   source order plus `order:`, which is where a row like this usually goes
   wrong the first time someone adds a fourth element to it. */
.c-order {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  align-items: center;
  gap: 2px 16px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--border);
}

.c-order:last-child { border-bottom: none; }

.c-order-what {
  grid-area: 2 / 1;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The product, small and quiet under what was bought — "Coins" over "500m",
   "Item" over "Hyperion". The kind labels the row; the detail is the row. */
.c-order-kind {
  grid-area: 1 / 1;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-2);
}

.c-order-when {
  grid-area: 1 / 2 / span 2 / auto;
  align-self: center;
  font-size: 12.5px;
  color: var(--text-2);
  white-space: nowrap;
}

/* An order with a price splits the right column the way the left one is split:
   the date drops to the lower row and the price takes the upper, so the two
   sides of the row read as two pairs rather than one pair and a stray. */
.c-order.has-price .c-order-when {
  grid-area: 2 / 2;
  align-self: auto;
  text-align: right;
}

.c-order-price {
  grid-area: 1 / 2;
  text-align: right;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}

/* ===== Empty, loading, and failure ======================================= */

.c-note { padding: 40px 24px; text-align: center; }

.c-note-title {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin-bottom: 6px;
}

.c-note-body {
  font-size: 13.5px;
  color: var(--text-2);
  max-width: 42ch;
  margin: 0 auto;
}

.c-note .btn { margin-top: 18px; }

/* The database's own words, kept whole. The admin panel learned that a generic
   message throws away the diagnosis exactly where it is needed.
   Boxed and left-aligned rather than centred: it is a quoted machine message
   sitting in a column of prose, and centring it made it read as another line
   of that prose that had gone strange. */
.c-note-detail {
  margin: 16px 0 14px;
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.25);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--text-2);
  word-break: break-word;
  text-align: left;
}

.light .c-note-detail { background: rgba(0, 0, 0, 0.04); }

/* ===== The gate ========================================================== */

/*
   THE ROOM. A photograph of the aurora over Kilpisjarvi, pressed down by a
   dark scrim, with the card on its own opaque panel over the top.

   WHY A PHOTO, after three rounds of drawn backdrops were rejected: this one
   is the only backdrop David picked out himself, and its green is the site's
   own accent - the card belongs to the picture rather than sitting on it.
   See login/AURORA.txt for the photographer and the licence; it is Unsplash,
   free for commercial use, which matters because this is a shop.

   Deliberately NOT one of /backgrounds/*.webp. Those are the profile pages'
   wallpapers, and reusing one made the front door look like a listing.

   TEXT NEVER SITS ON THE IMAGE. The scrim handles the room, and the card
   carries its own opaque background on top of that - which is exactly what
   Minecraft's own sign-in page does, and the reason it stays readable over a
   busy render.
*/
.c-gate {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 100dvh;
  padding: 24px;
}

/* Photo, scrim and floor in one layer, painted top-first. A second fixed
   layer at a lower z-index would be invisible under an opaque one - the
   mistake listing.css already made once. */
.c-gate::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(rgba(6, 7, 11, var(--c-scrim)), rgba(6, 7, 11, var(--c-scrim))),
    var(--c-photo, none) center / cover no-repeat,
    var(--c-floor);
}

/* The photograph is named once, and light mode unsets it. A browser only
   fetches a background-image whose element actually resolves to it, so a
   light-theme visitor never downloads the 96KB. */
.c-gate { --c-photo: url('/login/aurora.webp'); }
.light .c-gate { --c-photo: none; }

/* Light mode's one soft light, standing in for the photo. */
.light .c-gate::before {
  background:
    radial-gradient(52rem 40rem at 32% 14%, var(--c-glow), transparent 62%),
    var(--c-floor);
}

/* THE SPLIT. Left is the one thing to do, right is who you are signing in to. */
.c-gate-card {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
  width: min(880px, 100%);
  border: 1px solid var(--border-hover);
  border-radius: 20px;
  overflow: hidden;
  background: rgba(13, 15, 22, 0.92);
  backdrop-filter: blur(20px) saturate(120%);
  /* Depth is what separates a card from a div: a hairline of light along the
     top edge, a short shadow to lift it, and a long soft one to seat it. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 2px 8px rgba(0, 0, 0, 0.4),
    0 30px 70px rgba(0, 0, 0, 0.5);
}

.light .c-gate-card {
  background: rgba(255, 255, 255, 0.94);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 2px 8px rgba(0, 0, 0, 0.07),
    0 30px 70px rgba(0, 0, 0, 0.12);
}

/* The failure state drops the right half.
   Proof of the shop is the wrong thing to say next to "the door is jammed",
   and the panel's numbers are beside the point when the page is apologising. */
.c-gate-card.is-solo {
  grid-template-columns: minmax(0, 1fr);
  width: min(460px, 100%);
}

.c-gate-card.is-solo .c-gate-aside { display: none; }

.c-gate-action {
  display: flex;
  flex-direction: column;
  padding: 38px 38px 34px;
}

/* Mark, then a gap that does the work of a divider, then the heading. */
.c-gate-mark {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  margin-bottom: 38px;
  align-self: flex-start;
}

.c-gate-mark-tile {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: #000;
  display: grid;
  place-items: center;
  overflow: hidden;
  flex-shrink: 0;
}

/* favicon.png is white artwork on its own black square with generous padding
   baked in, so it gets a black tile and is scaled up to crop that padding back
   off. object-fit plus a transform, not a bigger width: an oversized img in a
   centred grid crops from whichever edge overflows first, which took a bite
   out of the mark. */
.c-gate-mark-tile img { width: 100%; height: 100%; object-fit: cover; transform: scale(1.4); }

.c-gate-wordmark {
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--text);
}

.c-gate-wordmark .c-accent { color: var(--accent); }

/* The three states swap inside this box, which fills the column and CENTRES
   its block.
   Pinning the button to the floor instead left a hole between the lede and the
   button: the card's height is set by the panel opposite, not by anything on
   this side, so there is simply more column here than there is content. A
   centred block reads as a card with room in it; a top-and-bottom split reads
   as a missing element. */
.c-gate-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  justify-content: center;
}

.c-gate-title {
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.1;
  margin-bottom: 10px;
}

.c-gate-lede {
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--text-2);
  max-width: 34ch;
}

.c-discord-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  margin-top: 28px;
  padding: 14px 20px;
  border: none;
  border-radius: 12px;
  background: var(--c-blurple);
  color: #fff;
  font-family: var(--font);
  font-size: 14.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s, transform 0.2s, box-shadow 0.2s;
}

.c-discord-btn:hover {
  background: var(--c-blurple-hover);
  transform: translateY(-1px);
  box-shadow: 0 8px 28px rgba(88, 101, 242, 0.3);
}

.c-discord-btn:active { transform: translateY(0); }

.c-gate-fine {
  margin-top: 14px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-2);
  opacity: 0.8;
  max-width: 36ch;
}

.c-gate-actions { display: flex; gap: 10px; margin-top: 28px; }

/* ===== The gate's right half: who you are signing in to =================== */

.c-gate-aside {
  position: relative;
  display: flex;
  border-left: 1px solid var(--border);
  background:
    linear-gradient(165deg, rgba(16, 185, 129, 0.08), transparent 60%),
    rgba(255, 255, 255, 0.015);
  overflow: hidden;
}

.light .c-gate-aside { background: linear-gradient(165deg, rgba(16, 185, 129, 0.09), transparent 60%); }

.c-gate-aside-glow {
  position: absolute;
  inset: auto -30% -45% -30%;
  height: 70%;
  background: radial-gradient(closest-side, var(--accent-glow), transparent);
  pointer-events: none;
}

.c-gate-aside-body {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 38px 34px 34px;
  width: 100%;
}

/* The claim the whole panel is evidence for, so it goes first and the numbers
   answer it. On its own it is just a slogan. */
.c-gate-pitch {
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.35;
  color: var(--text);
  max-width: 16ch;
  margin-bottom: 26px;
}

/* Three rows, label over figure, hairline between. A row rather than a grid of
   tiles: there are only three, and stacked they can be read down in one pass
   without the eye having to pick an order. */
.c-proof { display: flex; flex-direction: column; }

.c-proof-row {
  padding: 13px 0;
  border-top: 1px solid var(--border);
}

.c-proof-row:last-child { border-bottom: 1px solid var(--border); }

.c-proof-label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-2);
  margin-bottom: 3px;
}

.c-proof-value {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.15;
  color: var(--text);
}

.c-gate-aside-note {
  margin-top: auto;
  padding-top: 24px;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--text-2);
  max-width: 30ch;
}

.c-gate-aside-note a {
  color: var(--accent);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent);
  text-underline-offset: 3px;
}

.c-gate-aside-note a:hover { text-decoration-color: var(--accent); }

/* Under 780px the two halves stop fitting side by side. The aside is dropped
   rather than stacked: a phone screen has room for one job, and the job is
   signing in. */
@media (max-width: 780px) {
  .c-gate-card { grid-template-columns: minmax(0, 1fr); width: min(430px, 100%); }
  .c-gate-aside { display: none; }
  .c-gate-action { padding: 32px 28px 28px; }
  .c-gate-mark { margin-bottom: 30px; }
  .c-gate-title { font-size: 26px; }
}

/* ===== Quality floor ===================================================== */

:where(a, button):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 6px;
}

@media (prefers-reduced-motion: reduce) {
  .c-progress-fill,
  .c-discord-btn,
  .c-back svg { transition: none; }
}
