/*
 * The customer design system. One stylesheet, no build step, no framework.
 *
 * RTL-first by construction rather than by mirroring: every box uses logical
 * properties (inline-start/end, margin-inline) so the same rules lay out
 * correctly in either direction and a future English locale needs no second
 * sheet. Nothing here carries meaning on its own - a badge is a colour for a
 * label the server already decided, never a rule about what the label means.
 *
 * UX-1: this file is the **brand-free core**. Every rule below styles the
 * product; not one of them names a brand colour. The values live in semantic
 * tokens whose fallbacks are the neutral set declared here, and a brand profile
 * overrides them from `static/brands/<slug>/theme.css`, linked after this file.
 * Adding a brand therefore touches no rule in this stylesheet.
 *
 * The token names say what a thing is *for*, never what it looks like:
 * `--surface-raised`, not `--dark-grey-2`. That is what lets a neon dark brand
 * and a plain light one share every component below.
 */

/*
 * Cascade layers, declared before any rule so the order is fixed no matter what
 * loads when. `brand` beats `core`, so a brand token file overrides these values
 * without having to out-specify them - which is what went wrong the first time
 * this was built: the core dark block carried two compound selectors and quietly
 * outranked the brand's single `:root`.
 *
 * Only the TOKEN blocks are layered. Component rules below stay unlayered, which
 * puts them above both layers - correct, because a brand supplies values and
 * never selectors, so nothing there can collide.
 */
@layer core, brand;

@layer core {

:root {
  color-scheme: light;

  /* UX10-A 06. Which of a light/dark pair of pictures the page is showing. The
     theme is decided by the blocks below and by a brand's own sheet - never by
     the server - so a picture that has to match it reads these rather than
     guessing. Display values rather than a flag, because display is what a
     stylesheet can act on without a query it cannot write. */
  --display-light-theme: inline-block;
  --display-dark-theme: none;

  /* -- shape and rhythm ------------------------------------------------- */
  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 18px;
  --radius-pill: 999px;
  --gap: 1rem;
  --shell-width: 68rem;
  --shell-width-wide: 78rem;

  /* -- type ------------------------------------------------------------- */
  --font: "Vazirmatn", "IRANSans", "Sahel", "Segoe UI", Tahoma, "Noto Sans Arabic", sans-serif;
  --font-display: var(--font);
  --tracking-eyebrow: 0.16em;

  /* -- ground ----------------------------------------------------------- */
  --paper: #f5f6f8;
  --chrome: #ffffff;
  --surface: #ffffff;
  --surface-raised: #ffffff;
  --surface-sunken: #f0f2f5;

  /* -- text ------------------------------------------------------------- */
  --ink: #10151f;
  --ink-soft: #4d5766;
  --ink-faint: #6f7787;

  /* -- edges ------------------------------------------------------------ */
  --line: #dfe3e9;
  --line-strong: #c3cad4;

  /* -- accents ---------------------------------------------------------- */
  /* The primary action colour and the counter-accent a brand pairs with it. */
  --accent: #1c4f8b;
  --accent-strong: #143a68;
  --accent-soft: #e8f0fa;
  --accent-contrast: #ffffff;
  --accent-2: #4a3b86;
  --accent-2-soft: #eeebf7;
  --accent-2-contrast: #ffffff;

  /* -- status ----------------------------------------------------------- */
  --ok: #1f6b45;
  --ok-tint: #e4f3ea;
  --warn: #8a5a06;
  --warn-tint: #fbf0dc;
  --danger: #9a2c2c;
  --danger-tint: #fbe9e9;
  --info: #285a86;
  --info-tint: #e6f1f8;

  /* -- depth ------------------------------------------------------------ */
  --shadow: 0 1px 2px rgba(16, 21, 31, 0.06), 0 4px 16px rgba(16, 21, 31, 0.04);
  --shadow-lg: 0 2px 6px rgba(16, 21, 31, 0.08), 0 18px 48px rgba(16, 21, 31, 0.08);
  /* A brand with a neon identity sets this to a real glow; the neutral core
     leaves it flat, so an unbranded install looks deliberate rather than dim. */
  --glow: none;
  --glow-2: none;
  --ring: var(--accent);

  /* -- decorative surfaces ---------------------------------------------- */
  /* Used only by the marketing shell. A brand that wants no atmosphere leaves
     these transparent and every layout below still holds. */
  --hero-wash: transparent;
  --hero-veil: transparent;
  --grid-line: transparent;
  --hairline: linear-gradient(90deg, transparent, var(--line-strong), transparent);

  /* -- compatibility ----------------------------------------------------- */
  /* `--brand*` predates the semantic vocabulary and is still read by rules
     throughout this file. Aliasing rather than renaming keeps the UX-1 diff to
     the tokens themselves instead of thirty unrelated edits. */
  /* -- R1-UX atmosphere and fills ---------------------------------------- */
  /* Neutral by default: an unbranded install renders every layout below
     correctly with no light, no glow and no gradient. A brand turns them on. */
  --page-glow: none;
  --hero-key: none;

  /* UX-2. The homepage artwork, declared by the brand and never by the core.
     Three sources because art direction is not scaling: a landscape crop and a
     portrait composition are different pictures, not one picture at two sizes.
     `none` is a working value - an unbranded install shows the key light and
     the wash exactly as it did before there was any artwork to show. */
  --hero-art: none;
  --hero-art-sm: none;
  --hero-art-narrow: none;
  --hero-art-focus: 50% 42%;
  --hero-art-focus-narrow: 50% 40%;
  --hero-art-ground: var(--paper);
  --hero-ink-shadow: none;

  /* The scrim a phone gets. It is a separate token because the shape of the
     problem is different there: a wide hero has copy in a column with artwork
     beside it, and a narrow one has copy *through* the artwork, so where the
     picture may stay clear is a question only the narrow layout can answer.
     Defaults to the wide one, so a brand that has no opinion has no bug. */
  --hero-veil-narrow: var(--hero-veil);

  /* Depth over artwork. A brand that wants glass supplies a translucent
     surface and a blur; one that does not gets the ordinary raised surface and
     no filter, which is why the default is not a transparency. */
  --surface-glass: var(--surface-raised);
  --glass-blur: none;

  /* UX10-A. Artwork tiles. A caption on game art sits on the art's own dark scrim
     in both themes, so these are the same in light and dark by default; a brand
     may still restyle them here rather than by selector. */
  --media-ground: #0b1018;
  --media-edge: rgba(255, 255, 255, 0.1);
  --media-scrim: linear-gradient(180deg, rgba(4, 7, 12, 0) 40%, rgba(4, 7, 12, 0.62) 66%, rgba(4, 7, 12, 0.94) 100%);
  --media-ink: #ffffff;
  --media-ink-soft: rgba(255, 255, 255, 0.72);
  --media-ink-shadow: 0 1px 8px rgba(0, 0, 0, 0.6);
  --media-shadow: 0 8px 24px rgba(0, 0, 0, 0.24);
  --media-shadow-hover: 0 14px 32px rgba(0, 0, 0, 0.32);
  --media-chip-ground: rgba(8, 12, 20, 0.55);
  --media-chip-edge: rgba(255, 255, 255, 0.2);
  --media-chip-ink: rgba(255, 255, 255, 0.9);
  --media-fallback-edge: rgba(255, 255, 255, 0.28);
  --media-fallback-hatch: rgba(255, 255, 255, 0.035);
  --media-fallback-ink: rgba(255, 255, 255, 0.62);
  --media-status-soon: rgba(34, 94, 150, 0.92);
  --media-status-paused: rgba(138, 90, 6, 0.95);
  --media-status-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);

  /* Section punctuation. A brand may supply a band that separates two regions
     and a watermark that sits behind one; `none` means the page keeps its own
     flat transitions, which is what an unbranded install gets. */
  --divider-art: none;
  --section-watermark: none;

  /* A3.2. Artwork for the two sections that close the page. `none` is a working
     value: an unbranded install gets the same layout with a plain surface where
     the picture would be, and the closing band simply reads as a quiet panel. */
  --network-art: none;
  --network-art-narrow: var(--network-art);
  --network-veil: none;
  --closing-art: none;
  --closing-art-narrow: var(--closing-art);
  --closing-veil: linear-gradient(180deg, transparent, var(--paper));

  /* UX10-A correction 02. Artwork for the landing sections that were card grids
     and gradients before: the featured shelf and the route band. Each has a wide
     file and a narrow one, and each narrow one falls back to its wide file rather
     than to nothing, so a brand may supply one picture or two. (UX10-A 07 removed
     the panel section that had a third pair of tokens here.)

     A veil is a brand's own gradient over its own artwork, and `none` on both is
     the honest default: with no picture there is nothing to veil, and a tint over
     an empty panel would be a colour this sheet has no business choosing. */
  --featured-art: none;
  --featured-art-narrow: var(--featured-art);
  --featured-veil: none;

  /* Showcase tiles. The ground is what a tile looks like with no artwork at
     all, so a brand can declare a kind of play before its picture exists. */
  --tile-ground: var(--surface-raised);
  --tile-veil: linear-gradient(180deg, transparent 38%, var(--surface-raised) 92%);

  /* UX-3A. The authentication artwork, and the only thing the core knows about
     it is that there might be one. Signing in is not the homepage: it used to
     borrow the homepage's drawing, which made every future change to a
     marketing picture a change to the front door of the product. These four
     tokens are that door's own.

     The core sizes, crops, veils and hides the region. The brand says which
     picture goes in it, where the interesting part of that picture is, and what
     it takes to read words over it - because only the brand has seen it. `none`
     is a working value: an unbranded install gets the same shell with a plain
     panel where the picture would be. */
  --auth-art: none;
  --auth-art-position: 50% 30%;
  --auth-art-ground: var(--surface-sunken);
  --auth-art-veil: linear-gradient(180deg, transparent 30%, var(--surface-sunken) 94%);

  /* The colour of a secondary link on the authentication panel, and a separate
     token from the site-wide one because the two answer different questions.
     Everywhere else a link sits among running text and its colour is a brand
     signature; here it sits alone on a pale panel and is the only way out of a
     form somebody may be stuck in, so it has to clear AA on its own.

     Defaults to the site-wide brand link, so a brand that says nothing keeps
     exactly the behaviour it has today. One that measures its own accent and
     finds it short overrides this value alone - not the global link colour,
     which belongs to surfaces this token has no business changing. */
  --auth-link: var(--brand);

  /* UX-4. The customer dashboard's artwork, on the same terms as the front
     door's above: the core knows a picture might exist and nothing about which.

     Three regions, because they are three different jobs and a brand may have
     art for one and not the others - a hero band across the top, a support card
     that wants a photograph behind its words, and an illustration for the moment
     a customer owns nothing yet. Each has a `-mobile`/`-small` companion so a
     narrow viewport fetches a crop made for it instead of a 1920-wide file it
     will only ever see a third of.

     Every default is `none` or an ordinary surface, and that is a working
     configuration rather than a placeholder: an unbranded install gets the same
     dashboard with plain panels, which is what makes the layout below testable
     without a brand present. */
  --dashboard-hero-art: none;
  --dashboard-hero-art-mobile: none;
  --dashboard-hero-position: 50% 50%;
  --dashboard-hero-ground: var(--surface-sunken);
  --dashboard-hero-veil: linear-gradient(180deg, transparent, var(--surface-sunken));
  /* A narrow viewport reads a different crop and puts the copy under it rather
     than beside it, so the wash that carries the words is a different shape.
     Defaults to the wide one, so a brand that has only one still works. */
  --dashboard-hero-veil-mobile: var(--dashboard-hero-veil);
  --dashboard-hero-edge: var(--line);

  --dashboard-support-art: none;
  --dashboard-support-art-mobile: none;
  --dashboard-support-veil: linear-gradient(180deg, transparent, var(--surface-raised));

  --dashboard-controller-art: none;
  --dashboard-controller-art-small: none;

  /* What a summary card is lit by, and the ring behind its icon. Both resolve to
     nothing and to a plain tint by default, so the card is a card either way. */
  --dashboard-card-glow: none;
  --dashboard-icon-ring: var(--surface-sunken);

  /* The colour of small accent text on this page - the hero eyebrow, the second
     half of the greeting, the "see all" links - and a separate token from the
     brand accent for the reason UX-3 already found on the authentication panel:
     an accent tuned to carry a filled button is not necessarily one that clears
     AA as 13px text on a pale surface. Defaults to the brand accent, so a brand
     that says nothing keeps exactly what it has; one that measures its own and
     finds it short overrides this alone rather than the accent every button
     uses. */
  --dashboard-accent-text: var(--accent);

  /* -- UX-5 commerce ----------------------------------------------------
   *
   * The catalog, offer, checkout and payment-result surfaces, declared the same
   * way the dashboard's are: `none` and a plain tint by default, so a deployment
   * that supplies no artwork gets these pages on ordinary panels rather than a
   * broken imitation of somebody else's brand. A brand overrides the values -
   * never a selector - from its own token sheet.
   *
   * Each artwork token is *one* property whose value the brand redefines per
   * theme block, so the browser resolves exactly one file: the light sheet's
   * value is never fetched while a dark theme is active, and vice versa. */
  --commerce-hero-art: none;
  --commerce-hero-position: 50% 50%;
  --commerce-hero-ground: var(--surface-sunken);
  --commerce-hero-veil: linear-gradient(180deg, transparent, var(--surface-sunken));
  --commerce-hero-edge: var(--line);

  --commerce-tiers-art: none;
  --commerce-tiers-veil: linear-gradient(180deg, transparent, var(--surface-raised));

  --commerce-secure-art: none;
  --commerce-secure-veil: linear-gradient(180deg, transparent, var(--surface-raised));

  --commerce-success-art: none;
  --commerce-success-veil: linear-gradient(180deg, transparent, var(--surface-raised));

  --commerce-card-glow: none;
  --commerce-accent-text: var(--dashboard-accent-text);

  /* -- UX-6 active services ---------------------------------------------
   *
   * My Services, one owned service, its addresses and its renewal. Declared the
   * same way the dashboard's and the shop's are: `none` and a plain tint by
   * default, so a deployment that supplies no artwork gets these pages on
   * ordinary panels rather than a broken imitation of somebody else's brand. A
   * brand overrides the values - never a selector - from its own token sheet.
   *
   * Wide and narrow are two tokens rather than one file scaled, so a phone
   * fetches a phone-sized picture instead of downloading a 2000px composition to
   * show 390px of it. Each is *one* property the brand redefines per theme
   * block, so exactly one file is ever resolved. */
  --services-hero-art: none;
  --services-hero-art-mobile: none;
  --services-hero-position: 50% 50%;
  --services-hero-position-mobile: 50% 12%;
  --services-hero-ground: var(--surface-sunken);
  --services-hero-veil: linear-gradient(180deg, transparent, var(--surface-sunken));
  --services-hero-veil-mobile: var(--services-hero-veil);
  --services-hero-edge: var(--line);

  --services-scene-art: none;
  --services-scene-art-mobile: none;
  --services-scene-veil: linear-gradient(180deg, transparent, var(--surface-sunken));

  --services-frame-art: none;
  --services-frame-art-mobile: none;
  /* SERVICE-DETAIL-COMPACT-01: the creature on the detail band. None in the core. */
  --services-beast-art: none;
  --services-beast-position: 50% 14%;
  --services-frame-veil: linear-gradient(180deg, transparent, var(--surface-raised));

  --services-card-glow: none;
  --services-accent-text: var(--commerce-accent-text);

  /* PO-SVC-REFRESH-ORANGE: the service detail's "Check for updates" action. Its own semantic
   * accent so a brand can give that one control an identity without recolouring every quiet
   * button. The core values are exactly the quiet button's, so an unbranded install looks the
   * same as before. Text tokens carry readable colours; the accent is the icon, and the edge
   * the hairline border. */
  /* EMAIL-VERIFY-COOLDOWN-01: the short helper lines on the profile's email-verification card
   * (Spam/Junk, correcting the address, not sharing the link). A text colour, so every value
   * must stay readable as small text; the core uses its own warning ink, a brand may warm it. */
  --verification-hint-text: var(--warn);

  --service-refresh-text: var(--ink-soft);
  --service-refresh-text-hover: var(--ink);
  --service-refresh-accent: currentColor;
  --service-refresh-accent-hover: currentColor;
  --service-refresh-edge: transparent;
  --service-refresh-edge-hover: transparent;
  --service-refresh-tint: transparent;
  --service-refresh-tint-hover: var(--surface-sunken);
  --service-refresh-glow: none;
  --service-refresh-glow-hover: none;

  /* -- UX-7A wallet ------------------------------------------------------
   *
   * The wallet reuses the dashboard's approved hero pictures rather than adding
   * new ones, so its artwork tokens are *references* to the dashboard's tokens,
   * not files. That keeps every brand value where it already lives: a brand that
   * dresses the dashboard dresses the wallet with the same pictures in every
   * theme state and at both widths, and an unbranded install resolves both to
   * `none` and gets plain panels.
   *
   * The three summary accents are the core's own semantic colours, one per
   * figure, so the row reads as three different answers rather than one
   * repeated card. Text on them uses the ink variants a brand has already
   * measured for contrast. */
  --wallet-hero-art: var(--dashboard-hero-art);
  --wallet-hero-art-mobile: var(--dashboard-hero-art-mobile);
  --wallet-hero-position: var(--dashboard-hero-position);
  --wallet-hero-ground: var(--dashboard-hero-ground);
  --wallet-hero-veil: var(--dashboard-hero-veil);
  --wallet-hero-veil-mobile: var(--dashboard-hero-veil-mobile);
  --wallet-hero-edge: var(--dashboard-hero-edge);
  --wallet-card-glow: var(--dashboard-card-glow);
  --wallet-accent-text: var(--dashboard-accent-text);
  --wallet-total: var(--accent);
  --wallet-total-ink: var(--dashboard-accent-text);
  --wallet-available: var(--info);
  --wallet-available-ink: var(--info);
  --wallet-reserved: var(--accent-2);
  --wallet-reserved-ink: var(--accent-2);
  /* WALLET-UX-02. Cash to withdraw gets its own hue between the two it sits beside -
     derived from the palette, so a brand never has to name a fifth colour. */
  --wallet-withdrawable: color-mix(in srgb, var(--info) 60%, var(--accent-2));
  --wallet-withdrawable-ink: color-mix(in srgb, var(--info) 70%, var(--accent-2));
  --wallet-credit: var(--ok);
  --wallet-debit: var(--danger);

  /* UX-7B orders. The list has the wallet's composition - centred copy over the
     dashboard's pictures - so it takes the wallet's hero values rather than
     restating them; a brand that tunes the wallet band tunes this one too. */
  --orders-hero-art: var(--wallet-hero-art);
  --orders-hero-art-mobile: var(--wallet-hero-art-mobile);
  --orders-hero-position: var(--wallet-hero-position);
  --orders-hero-ground: var(--wallet-hero-ground);
  --orders-hero-veil: var(--wallet-hero-veil);
  --orders-hero-veil-mobile: var(--wallet-hero-veil-mobile);
  --orders-hero-edge: var(--wallet-hero-edge);
  --orders-card-glow: var(--wallet-card-glow);
  --orders-accent: var(--accent);
  --orders-accent-text: var(--wallet-accent-text);

  /* UX-7C notifications. The same centred band as the wallet and the orders. The
     three source tones only tint a decorative icon ring; every item also names
     its source and its read state in words. */
  --inbox-hero-art: var(--wallet-hero-art);
  --inbox-hero-art-mobile: var(--wallet-hero-art-mobile);
  --inbox-hero-position: var(--wallet-hero-position);
  --inbox-hero-ground: var(--wallet-hero-ground);
  --inbox-hero-veil: var(--wallet-hero-veil);
  --inbox-hero-veil-mobile: var(--wallet-hero-veil-mobile);
  --inbox-hero-edge: var(--wallet-hero-edge);
  --inbox-card-glow: var(--wallet-card-glow);
  --inbox-accent: var(--accent);
  --inbox-accent-text: var(--wallet-accent-text);
  --inbox-tone-payments: var(--accent);
  --inbox-tone-support: var(--info);
  --inbox-tone-dns: var(--accent-2);

  /* UX-7D support. The same centred band again. Staff and customer messages
     are told apart by words and by side; the staff tint is decoration. */
  --support-hero-art: var(--wallet-hero-art);
  --support-hero-art-mobile: var(--wallet-hero-art-mobile);
  --support-hero-position: var(--wallet-hero-position);
  --support-hero-ground: var(--wallet-hero-ground);
  --support-hero-veil: var(--wallet-hero-veil);
  --support-hero-veil-mobile: var(--wallet-hero-veil-mobile);
  --support-hero-edge: var(--wallet-hero-edge);
  --support-card-glow: var(--wallet-card-glow);
  --support-accent: var(--accent);
  --support-accent-text: var(--wallet-accent-text);
  --support-staff: var(--info);

  /* UX-8A content indexes. The index band has the account pages' composition -
     centred copy over the existing artwork - so it takes their hero values rather
     than restating them and needs no brand value of its own. A card with no
     editorial lead image stands on the ground the homepage tiles already use. */
  --content-hero-art: var(--wallet-hero-art);
  --content-hero-art-mobile: var(--wallet-hero-art-mobile);
  --content-hero-position: var(--wallet-hero-position);
  --content-hero-ground: var(--wallet-hero-ground);
  --content-hero-veil: var(--wallet-hero-veil);
  --content-hero-veil-mobile: var(--wallet-hero-veil-mobile);
  --content-hero-edge: var(--wallet-hero-edge);
  --content-accent-text: var(--wallet-accent-text);
  --content-card-ground: var(--tile-ground);

  /* UX-8A homepage discovery. Each card borrows artwork the brand already ships
     for another page by reference - the services scene for articles, the support
     desk for tutorials - so the section adds no picture and no brand value. An
     unbranded install draws the same cards on a plain ground. */
  --discovery-articles-art: var(--services-scene-art);
  /* The services scene's own phone picture is a near-empty backdrop drawn to sit
     behind text; a picture card needs the scene itself, and the wide one already
     fills a 16:9 frame almost whole. */
  --discovery-articles-art-mobile: var(--services-scene-art);
  --discovery-articles-position: 50% 30%;
  --discovery-tutorials-art: var(--dashboard-support-art);
  --discovery-tutorials-art-mobile: var(--dashboard-support-art-mobile);
  --discovery-tutorials-position: 28% 42%;

  --band: var(--surface-sunken);
  --hairline-soft: linear-gradient(90deg, transparent, var(--line), transparent);
  --edge: linear-gradient(90deg, transparent, var(--line-strong), transparent);
  --accent-edge: var(--line-strong);
  --accent-fill: var(--accent);
  --accent-2-fill: var(--accent-2);
  --glow-soft: none;
  --glow-strong: var(--shadow);

  --brand: var(--accent);
  --brand-dark: var(--accent-strong);
  --brand-tint: var(--accent-soft);
}

/*
 * Theme modes. The core ships a working dark palette so an unbranded install is
 * still usable in the dark, and a brand overrides the same three blocks.
 *
 * The pattern is deliberate and is repeated by every brand sheet:
 *   :root                                  the base palette
 *   @media (prefers-color-scheme: ...)     what the operating system asked for,
 *     :root:not([data-theme="<base>"])     unless the viewer overrode it
 *   :root[data-theme="..."]                the viewer's explicit choice
 *
 * With JavaScript disabled the middle block still applies, so "system" is the
 * behaviour you get for free and the toggle only ever adds a preference.
 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --display-light-theme: none;
    --display-dark-theme: inline-block;
    --paper: #12151b;
    --chrome: #171b22;
    --surface: #191d25;
    --surface-raised: #1f242e;
    --surface-sunken: #12161d;
    --ink: #eef1f6;
    --ink-soft: #b3bbc9;
    --ink-faint: #8b93a2;
    --line: #2a303b;
    --line-strong: #3a4150;
    --accent: #6ea8e8;
    --accent-strong: #9cc6f4;
    --accent-soft: #1b2b3d;
    --accent-contrast: #08111b;
    --accent-2: #a99bea;
    --accent-2-soft: #241f3a;
    --accent-2-contrast: #0d0a1a;
    --ok: #74d3a0;
    --ok-tint: #14291f;
    --warn: #e3b567;
    --warn-tint: #2c2415;
    --danger: #ef8f8f;
    --danger-tint: #2e1b1b;
    --info: #7fb6e0;
    --info-tint: #16232f;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3);
    --shadow-lg: 0 2px 8px rgba(0, 0, 0, 0.5), 0 20px 52px rgba(0, 0, 0, 0.45);
    --page-glow: none;
    --hero-key: none;
    --band: var(--surface-sunken);
    --hairline-soft: linear-gradient(90deg, transparent, var(--line), transparent);
    --edge: linear-gradient(90deg, transparent, var(--line-strong), transparent);
    --accent-edge: var(--line-strong);
    --accent-fill: var(--accent);
    --accent-2-fill: var(--accent-2);
    --glow-soft: none;
    --glow-strong: var(--shadow);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --display-light-theme: none;
  --display-dark-theme: inline-block;
  --paper: #12151b;
  --chrome: #171b22;
  --surface: #191d25;
  --surface-raised: #1f242e;
  --surface-sunken: #12161d;
  --ink: #eef1f6;
  --ink-soft: #b3bbc9;
  --ink-faint: #8b93a2;
  --line: #2a303b;
  --line-strong: #3a4150;
  --accent: #6ea8e8;
  --accent-strong: #9cc6f4;
  --accent-soft: #1b2b3d;
  --accent-contrast: #08111b;
  --accent-2: #a99bea;
  --accent-2-soft: #241f3a;
  --accent-2-contrast: #0d0a1a;
  --ok: #74d3a0;
  --ok-tint: #14291f;
  --warn: #e3b567;
  --warn-tint: #2c2415;
  --danger: #ef8f8f;
  --danger-tint: #2e1b1b;
  --info: #7fb6e0;
  --info-tint: #16232f;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3);
  --shadow-lg: 0 2px 8px rgba(0, 0, 0, 0.5), 0 20px 52px rgba(0, 0, 0, 0.45);
  --page-glow: none;
  --hero-key: none;
  --band: var(--surface-sunken);
  --hairline-soft: linear-gradient(90deg, transparent, var(--line), transparent);
  --edge: linear-gradient(90deg, transparent, var(--line-strong), transparent);
  --accent-edge: var(--line-strong);
  --accent-fill: var(--accent);
  --accent-2-fill: var(--accent-2);
  --glow-soft: none;
  --glow-strong: var(--shadow);
}

} /* @layer core - token blocks end here; everything below is unlayered. */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  /* Persian ascenders and descenders need more room than a Latin default gives them. */
  line-height: 1.85;
}

h1,
h2,
h3 {
  line-height: 1.5;
  margin: 0 0 0.6rem;
  font-weight: 700;
}

h1 {
  font-size: 1.5rem;
}

h2 {
  font-size: 1.2rem;
}

h3 {
  font-size: 1.02rem;
}

p {
  margin: 0 0 0.75rem;
}

a {
  color: var(--brand);
  text-decoration: none;
}

a:hover,
a:focus-visible {
  text-decoration: underline;
}

:focus-visible {
  outline: 3px solid var(--ring);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.skip-link {
  position: absolute;
  inset-inline-start: -9999px;
  top: 0;
  background: var(--surface);
  padding: 0.6rem 1rem;
  /* UX8-A11Y-04. Above the sticky header, which shares this top edge: below it, the first
     keyboard stop on every page was focused but painted under the chrome. */
  z-index: 50;
}

.skip-link:focus {
  inset-inline-start: 0;
}

/* ---------------------------------------------------------------- shell --- */

.site-header {
  background: var(--chrome);
  border-bottom: 1px solid var(--line);
  position: relative;
}

/* A one-pixel accent under the chrome. Decorative only, and invisible on a
   brand that leaves --hairline flat. */
.site-header::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: -1px;
  height: 1px;
  background: var(--hairline);
}

.site-header__inner,
.page,
.site-footer__inner {
  max-width: 68rem;
  margin: 0 auto;
  padding: 0 1rem;
}

.site-header__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 0;
}

.brand {
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--ink);
}

.site-nav {
  flex: 1 1 auto;
}

.site-nav ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  margin: 0;
  padding: 0;
}

.site-nav a {
  display: inline-block;
  padding: 0.35rem 0.6rem;
  border-radius: var(--radius-sm);
  color: var(--ink-soft);
}

.site-nav a:hover {
  background: var(--brand-tint);
  text-decoration: none;
}

.site-nav a[aria-current="page"] {
  background: var(--brand-tint);
  color: var(--brand-dark);
  font-weight: 700;
}

.count-pill {
  display: inline-block;
  min-width: 1.5rem;
  text-align: center;
  margin-inline-start: 0.25rem;
  padding: 0 0.35rem;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--accent-contrast);
  font-size: 0.78rem;
  line-height: 1.5rem;
}

.session-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.page {
  padding-top: 1.5rem;
  padding-bottom: 3rem;
}

.page-head {
  margin-bottom: 1.25rem;
}

.page-head p {
  color: var(--ink-soft);
  margin: 0;
}

.site-footer {
  border-top: 1px solid var(--line);
  background: var(--chrome);
  color: var(--ink-faint);
  font-size: 0.88rem;
}

.site-footer__inner {
  padding-top: 1rem;
  padding-bottom: 1rem;
}

/* -------------------------------------------------------- showcase rail --- */
/*
 * A strip of artwork cards an operator publishes in the CMS. Wide rather than
 * tall, several visible at once, and always scrollable: a rail's job is to look
 * like there is more of it than fits, which is a shape a grid cannot have.
 *
 * The scroller is the same element in both directions. Nothing here names left
 * or right; `scroll-padding-inline` and the logical margins do the mirroring,
 * and the arrows learn which way "next" is from the computed direction.
 */

.rail {
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scroll-snap-type: x proximity;
  scroll-padding-inline-start: 0;
  scrollbar-width: none;
}

.rail::-webkit-scrollbar {
  display: none;
}

.rail:focus-visible {
  outline: 3px solid var(--ring);
  outline-offset: 4px;
  border-radius: var(--radius-lg);
}

.rail__track {
  list-style: none;
  margin: 0;
  padding: 0.2rem 0 0.6rem;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: clamp(9.5rem, 17vw, 12.5rem);
  gap: 0.9rem;
}

.rail__item {
  scroll-snap-align: start;
}

/* Two buttons, and only once something is driving them. */
.rail__controls {
  display: none;
  gap: 0.4rem;
}

.js-rail .rail__controls {
  display: inline-flex;
}

.rail__control {
  display: inline-grid;
  place-items: center;
  width: 2.3rem;
  height: 2.3rem;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  color: var(--ink-soft);
  cursor: pointer;
  transition: border-color 140ms ease, color 140ms ease, opacity 140ms ease;
}

.rail__control:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}

.rail__control:disabled {
  opacity: 0.35;
  cursor: default;
}

.rail__control svg {
  width: 1.1rem;
  height: 1.1rem;
}

/* The one place direction is physical. A chevron is a picture of a direction, so
   it has to be mirrored where the reading order is; the label beside it stays
   "previous" and "next", which are positions and mirror themselves. */
[dir="rtl"] .rail__control svg {
  transform: scaleX(-1);
}

.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: var(--surface-raised);
  box-shadow: var(--shadow);
  overflow: hidden;
  transition: border-color 160ms ease, transform 160ms ease, box-shadow 160ms ease;
}

.tile:hover,
.tile:focus-within {
  border-color: var(--accent-edge);
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
}

/* The lit floor sits behind the picture and not under the caption: artwork with
   a transparent background gets something to stand on, and the words keep the
   card's own surface. */
.tile__frame {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--tile-ground);
}

.tile__art {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* A short lit edge under the artwork, which is the only place the brand's two
   colours touch a card. */
.tile__frame::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 1px;
  background: var(--edge);
  opacity: 0.75;
}

.tile__body {
  padding: 0.6rem 0.75rem 0.8rem;
}

.tile__title {
  display: block;
  font-size: 0.92rem;
  font-weight: 700;
  line-height: 1.5;
  color: var(--ink);
}

.tile__label {
  display: block;
  font-size: 0.78rem;
  line-height: 1.6;
  color: var(--ink-faint);
}

/* One link with real text, stretched over the whole card: a clickable box with
   no link in it is something a keyboard cannot reach and a screen reader cannot
   name. */
.tile__link {
  color: inherit;
}

.tile__link::after {
  content: "";
  position: absolute;
  inset: 0;
}

.tile__link:hover {
  text-decoration: none;
  color: var(--accent);
}

/* ------------------------------------------------------ section accents --- */
/*
 * Two ways a brand may punctuate the page, and the core supplies neither
 * picture. Both degrade to nothing: `none` is a working value, so an unbranded
 * install simply has flat transitions and no watermark.
 */

/* A full-bleed strip between two regions. The artwork a brand puts here carries
   its own ground, which will never be exactly the page's - so the band is masked
   away at every edge rather than butted against the section above it. A seam is
   what a divider is supposed to remove. */
.divider {
  height: clamp(2.75rem, 6vw, 5.5rem);
  margin-block: -0.5rem;
  background-image: var(--divider-art);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  /* A mask reads alpha, not colour, so the stops only have to be "opaque" and
     "not": `currentColor` is the first without naming a hue the core has no
     business naming, and the colour test is right to keep it that way. */
  -webkit-mask-image: radial-gradient(62% 130% at 50% 50%, currentColor 8%, transparent 74%);
  mask-image: radial-gradient(62% 130% at 50% 50%, currentColor 8%, transparent 74%);
  pointer-events: none;
}

/* A large, quiet mark behind a section's content. Behind is the whole
   requirement: it sits on its own layer under the text, never above it, and it
   is not a logo anybody is meant to read. */
.section--watermarked {
  position: relative;
  isolation: isolate;
}

.section--watermarked::before {
  content: "";
  position: absolute;
  inset: -1rem 0 0;
  z-index: -1;
  background-image: var(--section-watermark);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  pointer-events: none;
}

/* The watermark is a shape with a side, and a page that starts on the other
   side should not have it in the same corner. There is no logical
   `background-position`, so the layer is mirrored instead. */
[dir="rtl"] .section--watermarked::before {
  transform: scaleX(-1);
}

/* -------------------------------------------------------- the route band --- */
/*
 * UX10-A correction 02. One sentence over a picture of a connected world.
 *
 * The page's rhythm was card grid, card grid, card grid; this is a full-width
 * picture with copy held to one side of it, which is a different shape from
 * everything above and below it. The artwork is a brand token and the element
 * carrying it is empty, so it says nothing to a screen reader.
 *
 * Nothing in here is a measurement, and the copy says so. The band is scenery.
 */

.routes {
  position: relative;
  isolation: isolate;
  display: grid;
  align-items: center;
  margin-block: 2.75rem;
  min-height: clamp(20rem, 42vw, 28rem);
  padding: clamp(1.5rem, 4vw, 3rem);
  border: 1px solid var(--line);
  border-radius: calc(var(--radius-lg) * 1.4);
  background-color: var(--surface-sunken);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.routes__art {
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--network-veil), var(--network-art);
  background-size: cover, cover;
  background-position: center, 50% 30%;
  background-repeat: no-repeat, no-repeat;
  pointer-events: none;
}

@media (max-width: 719px) {
  .routes__art {
    background-image: var(--network-veil), var(--network-art-narrow);
    background-position: center, 50% 26%;
  }
}

.routes__copy {
  max-width: 34rem;
}

.routes h2 {
  font-size: clamp(1.5rem, 1.05rem + 1.6vw, 2.35rem);
  line-height: 1.4;
  margin: 0.7rem 0 0.75rem;
  text-wrap: balance;
  text-shadow: var(--hero-ink-shadow);
}

.routes__lede {
  margin: 0 0 0.9rem;
  color: var(--ink-soft);
  line-height: 1.95;
  text-shadow: var(--hero-ink-shadow);
}

/* One short line under the lede, lifted by the accent rule rather than by size:
   the section says three things and the third is the quietest of them. */
.routes__line {
  margin: 0 0 1.5rem;
  padding-inline-start: 0.8rem;
  border-inline-start: 2px solid var(--accent-edge);
  color: var(--ink-soft);
  font-size: 0.95rem;
  line-height: 1.85;
  text-shadow: var(--hero-ink-shadow);
}

.routes__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

/* ---------------------------------------------------------- the closing --- */
/*
 * The page used to stop. This is the one place the Beast is allowed to look
 * straight at the reader - the artwork carries the eyes, which is also why no
 * separate eye asset is layered here. Everything else on it is live HTML.
 */

.closing {
  position: relative;
  overflow: hidden;
  display: grid;
  place-items: center;
  min-height: clamp(22rem, 46vh, 30rem);
  background-color: var(--hero-art-ground);
  background-image: var(--closing-art);
  background-size: cover;
  /* Held high in the frame on purpose: the artwork's subject is at the top of
     it, and a centred crop of a 2.34:1 picture in a shorter band removes exactly
     the part the picture was chosen for. */
  background-position: 50% 18%;
  background-repeat: no-repeat;
}

@media (max-width: 719px) {
  .closing {
    background-image: var(--closing-art-narrow);
    background-position: 50% 12%;
  }
}

.closing::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--closing-veil);
  pointer-events: none;
}

.closing__inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 42rem;
  margin-inline: auto;
  padding: 3.25rem 1.25rem;
  text-align: center;
}

.closing h2 {
  font-size: clamp(1.7rem, 1.15rem + 1.9vw, 2.6rem);
  line-height: 1.35;
  margin-bottom: 0.7rem;
  text-wrap: balance;
  text-shadow: var(--hero-ink-shadow);
}

.closing p {
  color: var(--ink-soft);
  line-height: 1.9;
  margin: 0 auto 1.6rem;
  max-width: 32rem;
  text-shadow: var(--hero-ink-shadow);
}

.closing__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: center;
}

.closing__actions .btn {
  min-height: 3rem;
  padding-inline: 1.6rem;
  font-size: 1rem;
}

.closing__actions .btn--secondary {
  background: var(--surface-glass);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
}

/* ---------------------------------------------------------- footer trim --- */
/*
 * A3.2. The footer keeps every link it had - there are no invented destinations
 * here - and gains the weight to look like the end of the page rather than the
 * place it ran out. One lit hairline along the top, a quieter ground, and column
 * headings that read as labels instead of headlines.
 */

.site-footer {
  position: relative;
  background: var(--surface-sunken);
}

.site-footer::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 1px;
  background: var(--hairline);
}

.footer-col h2 {
  font-size: 0.78rem;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 0.9rem;
}

.footer-brand p {
  max-width: 22rem;
}

/* --------------------------------------------------------------- pieces --- */

.card {
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.1rem 1.2rem;
  box-shadow: var(--shadow);
  margin-bottom: var(--gap);
}

.card__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}

.card__head h2,
.card__head h3 {
  margin: 0;
}

.grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}

.stack > * + * {
  margin-block-start: 0.6rem;
}

.muted {
  color: var(--ink-faint);
}

.small {
  font-size: 0.88rem;
}

.figure {
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1.4;
}

.definition {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.2rem 0.8rem;
  margin: 0;
}

.definition dt {
  color: var(--ink-faint);
}

.definition dd {
  margin: 0;
}

.empty {
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  padding: 2rem 1.25rem;
  text-align: center;
  color: var(--ink-soft);
  background: var(--surface);
}

.empty__mark {
  display: block;
  width: 2.5rem;
  height: 2.5rem;
  margin: 0 auto 0.6rem;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 1.3rem;
  line-height: 2.5rem;
  font-weight: 700;
}

.empty__title {
  margin: 0 0 0.3rem;
  color: var(--ink);
  font-weight: 700;
}

.empty p {
  margin: 0 auto;
  max-width: 34rem;
}

.notice {
  border-inline-start: 4px solid var(--line-strong);
  background: var(--surface);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.85rem;
  margin-bottom: 0.75rem;
}

.notice--info {
  border-color: var(--info);
  background: var(--info-tint);
  color: var(--info);
}

.notice--warn {
  border-color: var(--warn);
  background: var(--warn-tint);
  color: var(--warn);
}

.notice--danger {
  border-color: var(--danger);
  background: var(--danger-tint);
  color: var(--danger);
}

.notice--ok {
  border-color: var(--ok);
  background: var(--ok-tint);
  color: var(--ok);
}

.badge {
  display: inline-block;
  padding: 0.1rem 0.55rem;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 700;
  background: var(--paper);
  color: var(--ink-soft);
  border: 1px solid var(--line-strong);
  white-space: nowrap;
}

.badge--ok {
  background: var(--ok-tint);
  color: var(--ok);
  border-color: var(--ok);
}

.badge--warn {
  background: var(--warn-tint);
  color: var(--warn);
  border-color: var(--warn);
}

.badge--danger {
  background: var(--danger-tint);
  color: var(--danger);
  border-color: var(--danger);
}

.badge--info {
  background: var(--info-tint);
  color: var(--info);
  border-color: var(--info);
}

.badge-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0.4rem 0;
  padding: 0;
  list-style: none;
}

.messages {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
}

.messages li {
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.85rem;
  margin-bottom: 0.4rem;
  border-inline-start: 4px solid var(--brand);
  background: var(--brand-tint);
  color: var(--brand-dark);
}

.messages li.success {
  border-color: var(--ok);
  background: var(--ok-tint);
  color: var(--ok);
}

.messages li.warning {
  border-color: var(--warn);
  background: var(--warn-tint);
  color: var(--warn);
}

.messages li.error {
  border-color: var(--danger);
  background: var(--danger-tint);
  color: var(--danger);
}

/* ---------------------------------------------------------------- table --- */

.table-scroll {
  overflow-x: auto;
}

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95rem;
}

table.data th,
table.data td {
  text-align: start;
  padding: 0.55rem 0.6rem;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

table.data thead th {
  color: var(--ink-faint);
  font-size: 0.85rem;
  font-weight: 700;
  border-bottom: 2px solid var(--line-strong);
  white-space: nowrap;
}

table.data tbody tr:last-child td {
  border-bottom: none;
}

.numeric {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ----------------------------------------------------------------- form --- */

.form-field {
  margin-bottom: 0.9rem;
}

.form-field label {
  display: block;
  font-weight: 700;
  margin-bottom: 0.25rem;
}

.form-field input[type="text"],
.form-field input[type="email"],
.form-field input[type="password"],
.form-field input[type="number"],
.form-field select,
.form-field textarea {
  width: 100%;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  color: var(--ink);
  font: inherit;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}

.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
  border-color: var(--accent);
  outline: none;
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.form-field .helptext,
.form-field ul.helptext {
  display: block;
  color: var(--ink-faint);
  font-size: 0.85rem;
  margin: 0.25rem 0 0;
  padding-inline-start: 1.1rem;
}

/* The invalid-field border lives with the rest of the auth form rules further
   down, where it is written strongly enough to actually reach the input. This
   selector could not: it is outranked by the base `input[type="..."]` rule. */

ul.errorlist {
  list-style: none;
  margin: 0.3rem 0 0;
  padding: 0;
  color: var(--danger);
  font-size: 0.88rem;
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  margin-top: 0.5rem;
}

.inline-form {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: center;
  margin: 0;
}

.inline-form input[type="number"] {
  width: 5rem;
  padding: 0.35rem 0.4rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  font: inherit;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  padding: 0.6rem 1.15rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: var(--accent);
  color: var(--accent-contrast);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
  box-shadow: var(--glow);
  transition: background-color 120ms ease, transform 120ms ease, box-shadow 120ms ease;
}

.btn:hover {
  background: var(--accent-strong);
  text-decoration: none;
}

.btn:active {
  transform: translateY(1px);
}

.btn--secondary {
  background: var(--surface-raised);
  color: var(--ink);
  border-color: var(--line-strong);
  box-shadow: none;
}

.btn--secondary:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--ink);
}

/* The counter-accent action. One per view at most - it exists so a brand with
   two signature colours can use the second without inventing a third button. */
.btn--alt {
  background: var(--accent-2);
  color: var(--accent-2-contrast);
  box-shadow: var(--glow-2);
}

.btn--alt:hover {
  background: var(--accent-2);
  filter: brightness(1.12);
}

.btn--quiet {
  background: transparent;
  color: var(--ink-soft);
  border-color: transparent;
  padding-inline: 0.4rem;
}

.btn--quiet:hover {
  background: var(--surface-sunken);
  color: var(--ink);
}

.btn--small {
  padding: 0.3rem 0.6rem;
  font-size: 0.88rem;
}

/* --------------------------------------------------------------- lists ---- */

.item-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.item-list > li {
  border-bottom: 1px solid var(--line);
  padding: 0.7rem 0;
}

.item-list > li:last-child {
  border-bottom: none;
}

.item-list > li.is-unread {
  background: var(--brand-tint);
  border-radius: var(--radius-sm);
  padding-inline: 0.6rem;
}

.item-head {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: baseline;
  justify-content: space-between;
}

@media (max-width: 640px) {
  body {
    font-size: 15px;
  }

  .site-header__bar {
    align-items: flex-start;
  }

  .card {
    padding: 0.85rem;
  }

  .definition {
    grid-template-columns: 1fr;
  }

  .definition dd {
    margin-bottom: 0.4rem;
  }
}

@media print {
  .site-header,
  .site-footer,
  .btn {
    display: none;
  }
}

/* ----------------------------------------------------- staff workspace --- */
/*
 * UX9-A. The operations room of the same product.
 *
 * The staff shell wears the active brand exactly as the customer surface does -
 * the same tokens, the same lockup, the same theme and language controls - and
 * says that it is internal through structure rather than through a second
 * palette: a staff badge beside the lockup, a lit accent rule under the chrome,
 * and the sections on a strip of their own beneath the top bar. Every colour in
 * this block is a token, so a brand swap re-colours the operator chrome with no
 * edit here, and the brand-free-core test reads this block like any other.
 *
 * It is denser than the customer surface on purpose: an operator scans for a
 * destination; they are not being welcomed.
 */

.staff .site-header {
  box-shadow: inset 0 -2px 0 color-mix(in srgb, var(--accent) 55%, transparent);
}

/* The lockup and the badge travel together, and push the session to the far end. */
.staff-identity {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  min-inline-size: 0;
  margin-inline-end: auto;
}

/* "Staff" in words, with a steady dot beside it. The word is the meaning; the
   dot is decoration and says nothing to a screen reader. */
.staff-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.12rem 0.55rem;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--line));
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}

.staff-tag::before {
  content: "";
  inline-size: 0.45rem;
  block-size: 0.45rem;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: var(--glow-soft);
}

/* The sections strip: every destination this actor may open, on its own row so
   seven of them never crowd the session controls off the bar. */
.staff-sections {
  border-block-start: 1px solid var(--line);
}

.staff-sections .site-nav ul {
  gap: 0.1rem 0.25rem;
  padding-block: 0.35rem;
}

.staff-sections .site-nav a {
  padding: 0.4rem 0.7rem;
  font-size: 0.9rem;
}

/* -- the launchpad ---------------------------------------------------------- */

.ops-launch {
  display: grid;
  gap: 1rem;
}

.ops-launch__note {
  margin: 0;
  max-inline-size: 64ch;
  color: var(--ink-soft);
  font-size: 0.92rem;
}

.ops-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.8rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 16.5rem), 1fr));
}

.ops-grid__item {
  display: flex;
  min-inline-size: 0;
}

/* One destination: an icon, its name as the one real link stretched over the
   card, and what the area is for. A thin lit edge on the logical start is the
   only ornament. */
.ops-card {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-content: start;
  gap: 0.25rem 0.85rem;
  inline-size: 100%;
  padding: 0.95rem 1rem 1rem;
  border: 1px solid var(--line);
  border-inline-start: 3px solid color-mix(in srgb, var(--accent) 55%, var(--line));
  border-radius: var(--radius);
  background: var(--surface-raised);
  box-shadow: var(--shadow);
  transition: border-color 140ms ease, box-shadow 140ms ease;
}

.ops-card:hover,
.ops-card:focus-within {
  border-color: var(--accent-edge);
  border-inline-start-color: var(--accent);
  box-shadow: var(--shadow-lg);
}

.ops-card:has(.ops-card__link:focus-visible) {
  outline: 3px solid var(--ring);
  outline-offset: 2px;
}

.ops-card__link:focus-visible {
  outline: none;
}

.ops-card__icon {
  grid-row: 1 / span 3;
  display: grid;
  place-items: center;
  inline-size: 2.4rem;
  block-size: 2.4rem;
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--line));
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent);
}

.ops-card__icon svg {
  inline-size: 1.25rem;
  block-size: 1.25rem;
}

.ops-card__title {
  margin: 0;
  font-size: 1rem;
  font-weight: 800;
  line-height: 1.5;
}

.ops-card__link {
  color: var(--ink);
  text-decoration: none;
}

.ops-card__link::after {
  content: "";
  position: absolute;
  inset: 0;
}

.ops-card__link:hover {
  text-decoration: none;
}

.ops-card__text {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.75;
  color: var(--ink-soft);
}

.ops-card__go {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin-block-start: 0.2rem;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--accent);
}

.ops-card__go svg {
  inline-size: 0.95rem;
  block-size: 0.95rem;
}

[dir="rtl"] .ops-card__go svg {
  transform: scaleX(-1);
}

/* -- narrow ----------------------------------------------------------------- */

/* The strip hands over to the same disclosure the customer shell uses. The
   lockup and the badge are placed as the customer header places its lockup -
   the badge on a second line of its own, so "Staff" stays readable at 320px
   instead of pushing the controls off the bar. */
@media (max-width: 900px) {
  .staff-sections {
    display: none;
  }

  .staff-identity {
    display: contents;
  }

  .staff-identity > .brand-lockup {
    grid-row: 1;
    grid-column: 2;
    justify-self: center;
  }

  .staff-identity > .staff-tag {
    grid-row: 2;
    grid-column: 1 / -1;
    justify-self: center;
  }
}
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.9rem;
}

.filter-bar a {
  padding: 0.25rem 0.7rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: 0.86rem;
  color: var(--ink-soft);
}

.filter-bar a[aria-current="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-contrast);
}

/* UX9-B1 - customer lookup and directory. Tokens only; the page keeps the staff shell. */
.directory-title {
  margin: 0;
  font-size: 1.1rem;
}

.directory-lookup__form {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 0.6rem 0.9rem;
  margin-block-start: 0.8rem;
}

.directory-lookup__form .form-field {
  flex: 1 1 16rem;
  margin-bottom: 0;
}

.directory-lookup__hint {
  margin-block: 0.5rem 0;
}

.directory-found {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem 1rem;
  margin-block: 0.9rem 0;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
}

.directory-found--none {
  color: var(--ink-soft);
}

.directory-found__identity {
  display: grid;
  gap: 0.15rem;
  min-inline-size: 0;
}

.directory-id {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 0.8rem;
  color: var(--ink-soft);
  overflow-wrap: anywhere;
  unicode-bidi: isolate;
}

.directory__total,
.directory__note {
  margin: 0;
}

.directory__note {
  margin-block-end: 0.8rem;
}

table.data.directory-table th,
table.data.directory-table td {
  vertical-align: middle;
}

.directory-table th[scope="row"] {
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
}

.directory-table .directory-id {
  display: inline-block;
  max-inline-size: 10.5rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}

.directory-table .directory-num {
  text-align: end;
  white-space: nowrap;
}

.directory-count {
  font-weight: 700;
}

.directory-table .directory-cell--pair {
  text-align: center;
  white-space: nowrap;
}

.directory-unavailable {
  color: var(--warn);
  font-weight: 600;
}

/* UX10-B - the customer's own name under the username, and contact values kept in their own
   direction (an email or a number is left-to-right inside an RTL page, never reordered). */
.directory-name {
  display: block;
  margin-block-start: 0.1rem;
  font-weight: 400;
  font-size: 0.86rem;
  color: var(--ink-soft);
  white-space: normal;
}

.directory-contact {
  unicode-bidi: isolate;
  overflow-wrap: anywhere;
}

.directory-missing {
  color: var(--ink-faint);
  font-style: italic;
}

/* UX10-B visual review - the Customers page is a finder over a wide table, so it alone takes
   most of a wide screen. Opt-in per page (staff/base.html `page_class`); every other Staff page
   keeps the standard reading width. The side gutters come from `.page` itself. */
.page.page--wide {
  max-width: min(100rem, 100%);
}

/* A page with a wide row of controls (Supported Titles) - roomier than the reading width, still
   comfortably short of the Customers finder and never edge to edge. */
.page.page--roomy {
  max-width: min(84rem, 100%);
}

/* A coupon's state change asks for its reason in the row: field and button as one control, and
   the whole thing wraps onto its own line before it squeezes the table. */
.coupon-state-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}

.coupon-state-form__reason {
  flex: 1 1 8rem;
  min-inline-size: 0;
  max-inline-size: 14rem;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  color: var(--ink);
  font: inherit;
  font-size: 0.86rem;
}

.coupon-state-form__reason:focus {
  border-color: var(--accent);
  outline: none;
  background: var(--surface);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.ops-table .coupon-action {
  white-space: normal;
}

/* The search is the page's main control: one field-and-button group wide enough for a full
   name, an email fragment or a mobile number, with Clear beside it; the whole row on a narrow
   screen. Flex order follows the writing direction, so in RTL the field is on the right and its
   button directly to its left. */
.directory-search {
  margin-block-start: 0.8rem;
}

.directory-search__label {
  display: block;
  margin-block-end: 0.35rem;
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--ink);
}

.directory-search__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 0.75rem;
}

.directory-search__group {
  display: flex;
  align-items: stretch;
  gap: 0.5rem;
  flex: 1 1 26rem;
  max-inline-size: 42rem;
}

.directory-search__input {
  flex: 1 1 auto;
  min-inline-size: 0;
  inline-size: 100%;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  color: var(--ink);
  font: inherit;
  transition: border-color 140ms ease, box-shadow 140ms ease, background-color 140ms ease;
}

.directory-search__input:hover {
  background: var(--surface);
}

.directory-search__input:focus {
  border-color: var(--accent);
  outline: none;
  background: var(--surface);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.directory-search__button {
  flex: 0 0 auto;
}

/* The person first, the account handle under it. */
.directory-primary {
  display: block;
  font-weight: 700;
  color: var(--ink);
}

.directory-secondary {
  display: block;
  margin-block-start: 0.1rem;
  font-weight: 400;
  font-size: 0.86rem;
  color: var(--ink-soft);
  white-space: normal;
}

/* Balance and available, or total and active, as labelled pairs inside one cell. */
.directory-figures {
  display: grid;
  gap: 0.15rem;
  margin: 0;
}

/* Each label sits right against its own value - "Total: 3", "Balance: 90,000 Toman" - so a
   zero can never be read as belonging to the other line. */
.directory-figures > div {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: flex-start;
  gap: 0 0.35rem;
}

.directory-figures dt {
  color: var(--ink-soft);
  font-size: 0.82rem;
  font-weight: 600;
}

.directory-figures dt::after {
  content: ":";
}

.directory-figures dd {
  margin: 0;
  white-space: nowrap;
}

@media (min-width: 1200px) {
  /* A whole address on one line wherever it fits; a genuinely long one still breaks inside the
     cell rather than pushing the table off the page. */
  .directory-table--profile .directory-cell--contact {
    min-inline-size: 12rem;
  }

  .directory-table .directory-contact {
    overflow-wrap: break-word;
    word-break: normal;
  }

  .directory-table .directory-cell--figures {
    min-inline-size: 11rem;
  }

  .directory-table .directory-cell--status {
    white-space: nowrap;
  }
}

@media (max-width: 1199px) {
  /* In the stacked card each contact value and each labelled pair takes the row, so a long
     address or the wallet's two figures are never squeezed into a narrow grid track. */
  .directory-table .directory-cell--contact,
  .directory-table .directory-cell--figures {
    grid-column: 1 / -1;
  }

  .directory-figures {
    max-inline-size: 22rem;
  }
}

.ops-profile__head {
  margin-block-start: 1rem;
}

.directory-action {
  text-align: end;
  white-space: nowrap;
}

.pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin-block-start: 1rem;
}

.pager__status {
  color: var(--ink-soft);
  font-size: 0.9rem;
}

.pager__edge {
  opacity: 0.45;
  pointer-events: none;
}

/* Below a wide desktop - tablets and small laptops included - each customer becomes a readable
   block instead of an eight-column table that would scroll the page sideways. */
@media (max-width: 1199px) {
  .directory-table,
  .directory-table tbody,
  .directory-table th[scope="row"],
  .directory-table td {
    display: block;
  }

  .directory-table thead {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .directory-table tr {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 7.5rem), 1fr));
    gap: 0.7rem 1rem;
    margin-block-end: 0.7rem;
    padding: 0.8rem 0.9rem;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface-raised);
  }

  /* Out-rank the base data-table cell rule, so a card carries no table rules or cell padding. */
  table.data.directory-table th[scope="row"],
  table.data.directory-table td {
    padding: 0;
    border: 0;
  }

  .directory-table th[scope="row"] {
    grid-column: 1 / -1;
    font-size: 1.02rem;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .directory-table td[data-label]::before {
    content: attr(data-label);
    display: block;
    margin-block-end: 0.1rem;
    color: var(--ink-faint);
    font-size: 0.74rem;
    font-weight: 700;
  }

  .directory-table .directory-num {
    text-align: start;
  }

  .directory-table .directory-cell--id,
  .directory-table .directory-cell--pair,
  .directory-table .directory-action {
    grid-column: 1 / -1;
  }

  .directory-table .directory-cell--pair {
    text-align: start;
  }

  .directory-table .directory-id {
    display: inline;
    max-inline-size: none;
    white-space: normal;
    overflow: visible;
  }

  .directory-table .directory-action .btn {
    display: flex;
    justify-content: center;
    min-block-size: 2.75rem;
  }
}

/* ============================================================================
   UX9-BC - operations core. Shared pieces for customer context, support, finance,
   coupons and audit. Tokens only, like the rest of the staff block.
   ============================================================================ */
.ops-back {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-block-end: 0.9rem;
  font-size: 0.92rem;
  font-weight: 600;
}

.ops-back__icon {
  inline-size: 1rem;
  block-size: 1rem;
  flex: none;
}

[dir="rtl"] .ops-back__icon {
  transform: scaleX(-1);
}

.ops-section-title {
  margin: 1.5rem 0 0.6rem;
  font-size: 0.82rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

:lang(fa) .ops-section-title {
  letter-spacing: 0;
  text-transform: none;
  font-size: 0.9rem;
}

.ops-grid-2 {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  align-items: start;
  margin-bottom: var(--gap);
}

.ops-grid-2 > .card {
  margin-bottom: 0;
}

.ops-panel__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem 0.8rem;
  margin-block-end: 0.75rem;
}

.ops-panel__head h2,
.ops-panel__head h3 {
  margin: 0;
  font-size: 1.05rem;
}

.ops-panel__meta {
  color: var(--ink-faint);
  font-size: 0.82rem;
}

.ops-note {
  margin: 0.6rem 0 0;
}

.ops-summary {
  display: grid;
  gap: 0.8rem 1.4rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
  margin: 0;
}

.ops-summary--stack {
  grid-template-columns: minmax(0, 1fr);
  gap: 0.6rem;
}

.ops-summary > div {
  min-inline-size: 0;
}

/* A value too long for one summary column (the whole Customer ID) takes a row of its own, at
   any column count, so it never runs into the field beside it. */
.ops-summary > .ops-summary__wide {
  grid-column: 1 / -1;
}

.ops-summary dt,
.ops-figures dt,
.ops-access dt {
  color: var(--ink-faint);
  font-size: 0.78rem;
  font-weight: 700;
}

.ops-summary dd {
  margin: 0.1rem 0 0;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.ops-id,
.ops-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 0.82rem;
  unicode-bidi: isolate;
  overflow-wrap: anywhere;
}

.ops-id {
  color: var(--ink-soft);
}

/* UX10-B. A table identifier is shown shortened (the full value is its title and a
   screen-reader copy), so it never breaks mid-token; the Identity panel's full Customer ID stays
   on one line wherever the panel has room, and only a genuinely narrow screen wraps it. */
.ops-id--compact {
  white-space: nowrap;
  overflow-wrap: normal;
}

@media (min-width: 40rem) {
  .ops-id--whole {
    white-space: nowrap;
    overflow-wrap: normal;
  }
}

.ops-figures {
  display: grid;
  gap: 0.6rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr));
  margin: 0;
}

.ops-figures > div {
  padding: 0.65rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
}

.ops-figures dd {
  margin: 0.15rem 0 0;
  font-size: 1.15rem;
  font-weight: 800;
}

.ops-state {
  display: grid;
  gap: 0.15rem;
  margin: 0;
  padding: 0.7rem 0.85rem;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
}

.ops-state__label {
  font-size: 0.75rem;
  font-weight: 800;
}

.ops-state--locked {
  border: 1px dashed var(--line-strong);
  background: var(--surface-sunken);
  color: var(--ink-faint);
}

.ops-state--unavailable {
  border: 1px solid var(--warn);
  background: var(--warn-tint);
  color: var(--warn);
}

.ops-state--empty {
  border: 1px solid var(--line);
  color: var(--ink-soft);
}

.ops-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.ops-list__item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 0.7rem;
  padding-block: 0.55rem;
  border-bottom: 1px solid var(--line);
}

.ops-list__item:last-child {
  border-bottom: 0;
}

.ops-list__title {
  font-weight: 700;
  overflow-wrap: anywhere;
}

.ops-list__meta {
  margin-inline-start: auto;
  color: var(--ink-faint);
  font-size: 0.82rem;
}

.ops-plain-list {
  margin: 0;
  padding-inline-start: 1.1rem;
}

.ops-plain-list > li + li {
  margin-block-start: 0.35rem;
}

.ops-access {
  display: grid;
  gap: 0.45rem;
  margin: 0;
}

.ops-access > div {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.3rem 0.8rem;
}

.ops-access dd {
  margin: 0;
}

.ops-finance-facts {
  margin-block-start: var(--gap);
}

.ops-filters {
  display: grid;
  gap: 0.2rem;
  margin-block-end: 0.4rem;
}

.filter-bar__label {
  align-self: center;
  margin-inline-end: 0.2rem;
  color: var(--ink-faint);
  font-size: 0.78rem;
  font-weight: 700;
}

.ops-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45rem;
}

/* Doubled class: the core .btn is declared again further down this sheet, so a single-class
   modifier here would lose to it and a rejection would look exactly like an approval. */
.btn.btn--danger-quiet {
  background: transparent;
  color: var(--danger);
  border: 1px solid var(--danger);
  box-shadow: none;
}

.btn.btn--danger-quiet:hover,
.btn.btn--danger-quiet:focus-visible {
  background: var(--danger-tint);
  color: var(--danger);
  filter: none;
  box-shadow: none;
}

/* SCS-P12. The one irreversible action, the final "Delete permanently" on its confirmation page.
   Solid, so it is unlike every other button; its label says what it does, so colour is never the
   only warning. Same doubled-class reason as above. */
.btn.btn--danger {
  background: var(--danger);
  color: var(--danger-tint);
  border: 1px solid var(--danger);
  box-shadow: none;
}

.btn.btn--danger:hover,
.btn.btn--danger:focus-visible {
  filter: brightness(1.1);
  box-shadow: none;
}

.ops-form {
  display: grid;
  gap: 0 1rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  align-items: start;
}

.ops-form__wide {
  grid-column: 1 / -1;
}

/* Tables: semantic tables where comparison matters, stacked cards when narrow. */
table.data.ops-table th,
table.data.ops-table td {
  vertical-align: middle;
}

.ops-table th[scope="row"] {
  font-weight: 700;
  color: var(--ink);
}

.ops-table .ops-num {
  text-align: end;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.ops-table .ops-actions-cell {
  text-align: end;
}

.ops-table .ops-actions-cell .ops-actions {
  justify-content: flex-end;
}

.ops-row-link {
  font-weight: 700;
  overflow-wrap: anywhere;
}

/* Support: the conversation, and two composers that can never be confused. */
.ops-layout {
  display: grid;
  gap: var(--gap);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}

.ops-layout__main > .card:last-child,
.ops-layout__aside > .card:last-child {
  margin-bottom: 0;
}

@media (min-width: 1080px) {
  .ops-layout {
    grid-template-columns: minmax(0, 1fr) minmax(16rem, 21rem);
  }
}

.ops-thread {
  display: grid;
  gap: 0.7rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ops-message {
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--line);
  border-inline-start-width: 4px;
  border-radius: var(--radius);
  background: var(--surface-raised);
}

.ops-message--customer {
  border-inline-start-color: var(--line-strong);
}

.ops-message--staff {
  border-inline-start-color: var(--accent);
}

.ops-message--internal {
  border-style: dashed;
  border-color: var(--warn);
  border-inline-start-style: solid;
  background: var(--warn-tint);
}

.ops-message--system {
  background: var(--surface-sunken);
}

.ops-message__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.6rem;
  margin-block-end: 0.35rem;
}

.ops-message__when {
  margin-inline-start: auto;
  color: var(--ink-faint);
  font-size: 0.8rem;
}

.ops-message__body {
  margin: 0;
  overflow-wrap: anywhere;
}

.ops-tag {
  display: inline-flex;
  align-items: center;
  padding: 0.05rem 0.5rem;
  border: 1px solid currentColor;
  border-radius: var(--radius-pill);
  font-size: 0.72rem;
  font-weight: 800;
  white-space: nowrap;
}

.ops-tag--internal {
  color: var(--warn);
}

.ops-tag--visible {
  color: var(--ok);
}

.ops-composer--internal {
  border: 1px dashed var(--warn);
  background: var(--warn-tint);
}

@media (max-width: 860px) {
  .ops-table-wrap {
    overflow: visible;
  }

  table.data.ops-table,
  .ops-table tbody,
  .ops-table tfoot,
  .ops-table th,
  .ops-table td {
    display: block;
  }

  .ops-table thead {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .ops-table tr {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 8.5rem), 1fr));
    gap: 0.55rem 1rem;
    margin-block-end: 0.65rem;
    padding: 0.75rem 0.85rem;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface-raised);
  }

  table.data.ops-table th,
  table.data.ops-table td {
    padding: 0;
    border: 0;
  }

  .ops-table .ops-cell--lead,
  .ops-table .ops-cell--wide,
  .ops-table .ops-actions-cell {
    grid-column: 1 / -1;
  }

  .ops-table [data-label]::before {
    content: attr(data-label);
    display: block;
    margin-block-end: 0.1rem;
    color: var(--ink-faint);
    font-size: 0.72rem;
    font-weight: 700;
  }

  .ops-table .ops-cell--lead[data-label]::before {
    display: none;
  }

  .ops-table .ops-num,
  .ops-table .ops-actions-cell {
    text-align: start;
  }

  .ops-table .ops-actions-cell .ops-actions {
    justify-content: flex-start;
  }

  .ops-actions .btn {
    min-block-size: 2.75rem;
  }
}

/* UX9-DE - staff closure: the pieces catalog, content and the finance report needed that the
   operations layer did not already have. Tokens only. */
.ops-lede {
  max-inline-size: 60rem;
  margin-block: 0 var(--gap);
}

.ops-form--single {
  grid-template-columns: minmax(0, 1fr);
}

.ops-lifecycle {
  margin-block-start: 0.9rem;
  padding-block-start: 0.8rem;
  border-block-start: 1px solid var(--line);
}

.ops-config {
  border-inline-start: 3px solid var(--line-strong);
}

.ops-fieldset {
  margin: 0 0 0.9rem;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.ops-fieldset legend {
  padding-inline: 0.3rem;
  font-weight: 700;
}

.ops-check {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-block-size: 2.2rem;
  margin-inline-end: 1rem;
}

.ops-grants {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  padding: 0;
  list-style: none;
}

.ops-grants > li + li {
  margin-block-start: 0;
}

.ops-doorway {
  margin-block-start: 0.9rem;
}

/* The shared table rule drops the last row's cell borders but only for td; a row header cell
   kept its line, which drew a short stray rule under the last row of every staff table. */
.ops-table tbody tr:last-child th,
.directory-table tbody tr:last-child th {
  border-bottom: none;
}

/* Django's date-time widget is not in the shared input list; staff forms render it. */
.staff .form-field input[type="datetime-local"] {
  width: 100%;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  color: var(--ink);
  font: inherit;
}

.staff .form-field--invalid input,
.staff .form-field--invalid select,
.staff .form-field--invalid textarea {
  border-color: var(--danger);
}

/* SCS-P11. The Studio editor groups each body block, and each Tutorial step inside it, in a
   <fieldset>. A fieldset defaults to `min-inline-size: min-content`, so one long choice - an
   uploaded-video or library-image title in a full-width select - set the minimum width of the
   whole block and pushed a narrow phone's page sideways. Letting these two groups shrink to
   their container keeps every control at the column's width; the select still shows the chosen
   title and its native list shows the rest. */
.studio-block,
.studio-step {
  min-inline-size: 0;
}

/* The uploaded-video search and file inputs are not in the shared full-width input list; the
   native file picker's intrinsic width is wider than a step's column on a 320px screen. */
.studio-video__tools input {
  max-inline-size: 100%;
}

/* ------------------------------------------------------- CSP utilities ---- */
/*
 * P16-D. These exist so no template needs a `style` attribute.
 *
 * A Content-Security-Policy of `style-src 'self'` blocks inline style
 * attributes as well as inline <style> blocks, and the customer surface is
 * enforcing that policy - so the six attributes that used to live in the
 * templates moved here rather than the policy being widened to accommodate
 * them. There is no `unsafe-inline` on the customer surface, and there is
 * nothing left that would need one.
 */
.card--narrow {
  max-width: 26rem;
  margin-inline: auto;
}

.card--form {
  max-width: 28rem;
  margin-inline: auto;
}

.text-center {
  text-align: center;
}

.flush {
  margin: 0;
}

.push-inline-end {
  margin-inline-start: auto;
}

.spaced-above {
  margin-top: 1rem;
}

/* Present for a screen reader, absent for everyone else. Used for the labels on
   controls whose meaning is carried by an icon. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* ====================================================== R1-UX elevation === */
/*
 * Shell chrome, atmosphere, marketing surfaces, auth and dashboard.
 *
 * Still brand-free. Every rule reads the semantic tokens declared in the core
 * layer above, so a brand changes how all of this looks by changing values and
 * never by overriding a selector. The atmosphere tokens - --hero-wash,
 * --page-glow, --grid-line, --glow, --edge - are the ones that carry a brand's
 * personality, and every layout here is correct when all of them are flat.
 *
 * The depth model is three steps and no more: --paper is the ground, --surface
 * is a panel on it, --surface-raised is a panel that wants attention. Anything
 * that needs to feel further forward earns it with an edge or a glow, not with a
 * fourth grey.
 */

/* ------------------------------------------------------------ atmosphere -- */
/*
 * One fixed light layer behind the whole document rather than a gradient per
 * section. Fixed, so scrolling moves content through the light instead of
 * dragging the light along with it - which is most of the difference between a
 * page that feels lit and one that feels painted.
 *
 * It is a single composited layer with no blur filter and no animation, so it
 * costs one paint and nothing per frame.
 */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -2;
  background: var(--page-glow);
  pointer-events: none;
}

/* The technical grid. Masked to fade out downward so it reads as texture near
   the top of the page and disappears rather than tiling forever. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 54px 54px;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, 0.35) 45%, transparent 80%);
  mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, 0.35) 45%, transparent 80%);
  pointer-events: none;
}

/* ------------------------------------------------------------- typography - */

h1,
h2,
h3 {
  font-family: var(--font-display);
  letter-spacing: -0.005em;
}

h1 {
  font-size: clamp(1.55rem, 1.2rem + 1.2vw, 2.1rem);
  line-height: 1.42;
  font-weight: 800;
}

h2 {
  font-size: clamp(1.2rem, 1.05rem + 0.6vw, 1.5rem);
  line-height: 1.5;
  font-weight: 800;
}

h3 {
  font-size: 1.05rem;
  line-height: 1.55;
  font-weight: 700;
}

/* Persian ascenders and descenders need the room; Latin at the same size does
   not, and long Latin runs inside a Persian paragraph look loose if they get it.
   Body line-height stays generous, headings tighten. */
.lede {
  font-size: 1.05rem;
  line-height: 1.9;
  color: var(--ink-soft);
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  color: var(--accent);
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--accent-soft);
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
}

.eyebrow::before {
  content: "";
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent);
}

/* ------------------------------------------------------------- lockup ----- */

.brand-lockup {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  text-decoration: none;
  color: var(--ink);
}

.brand-lockup:hover {
  text-decoration: none;
}

/* A3: the mark is a raster tile that carries its own corner radius, so the
   radius here is matched to it rather than added on top of it - rounding a
   rounded square twice clips the corners of the artwork. */
.brand-lockup__mark {
  display: block;
  width: 2.25rem;
  height: 2.25rem;
  flex: 0 0 auto;
  border-radius: 0.55rem;
  box-shadow: var(--glow-soft);
}

.brand-lockup__text {
  display: flex;
  flex-direction: column;
  line-height: 1.12;
}

.brand-lockup__name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.16rem;
  letter-spacing: 0.005em;
}

.brand-lockup__tagline {
  font-size: 0.62rem;
  color: var(--ink-faint);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-top: 0.12rem;
}

/* ------------------------------------------------------------- controls --- */
/*
 * Theme and language sit in one segmented cluster so they read as a single
 * settings control rather than two loose buttons. They are chrome, not actions:
 * quieter than any button that does something to the customer's account.
 */

.control-cluster {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  overflow: hidden;
}

.control-cluster > * + * {
  border-inline-start: 1px solid var(--line);
}

.control {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.4rem 0.7rem;
  border: 0;
  background: transparent;
  color: var(--ink-soft);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  line-height: 1.4;
}

.control:hover {
  background: var(--accent-soft);
  color: var(--accent);
  text-decoration: none;
}

.control__icon {
  width: 1rem;
  height: 1rem;
  flex: 0 0 auto;
}

/* The theme control is hidden until the script that runs it announces itself, so
   a browser without JavaScript is never shown a button that cannot work. */
.theme-toggle {
  display: none;
}

.js-theme .theme-toggle {
  display: inline-flex;
}

/* Three glyphs, all present; CSS reveals the one matching the resolved mode, so
   the script swaps an attribute and never markup. */
.theme-toggle__icon--system,
.theme-toggle__icon--light,
.theme-toggle__icon--dark {
  display: none;
}

:root:not([data-theme]) .theme-toggle__icon--system,
:root[data-theme="light"] .theme-toggle__icon--light,
:root[data-theme="dark"] .theme-toggle__icon--dark {
  display: block;
}

/* One press, one language. The form is only a wrapper for the POST - the
   button is the control, so it sits in the cluster on exactly the same terms
   as the theme toggle beside it. */
.lang-form {
  display: inline-flex;
  margin: 0;
}

.lang-switch {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

/* ---------------------------------------------------------- site header --- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--chrome);
  border-bottom: 1px solid var(--line);
}

/* The signature hairline: a two-colour thread under the chrome that is the first
   thing a brand's palette says on any page. Flat brands leave it invisible. */
.site-header::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: -1px;
  height: 1px;
  background: var(--hairline);
}

.site-header__bar {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  padding: 0.85rem 0;
  min-height: 4.25rem;
}

.site-nav {
  flex: 1 1 auto;
}

.site-nav ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.15rem;
  margin: 0;
  padding: 0;
}

.site-nav a {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.45rem 0.75rem;
  border-radius: var(--radius);
  color: var(--ink-soft);
  font-weight: 600;
  font-size: 0.95rem;
  transition: background-color 140ms ease, color 140ms ease;
}

.site-nav a:hover {
  background: var(--surface-sunken);
  color: var(--ink);
  text-decoration: none;
}

.site-nav a[aria-current="page"] {
  color: var(--accent);
  background: var(--accent-soft);
}

/* The active marker: a lit rule under the current section rather than a bolder
   weight, so the nav does not reflow as the customer moves around it. */
.site-nav a[aria-current="page"]::after {
  content: "";
  position: absolute;
  inset-inline: 0.75rem;
  bottom: 0.1rem;
  height: 2px;
  border-radius: 2px;
  background: var(--accent);
  box-shadow: var(--glow-soft);
}

.session-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex: 0 0 auto;
}

.session-user {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.3rem 0.7rem 0.3rem 0.35rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  font-size: 0.86rem;
  color: var(--ink-soft);
}

.session-user__avatar {
  display: grid;
  place-items: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 800;
  font-size: 0.8rem;
  line-height: 1;
}

.count-pill {
  display: inline-grid;
  place-items: center;
  min-width: 1.35rem;
  height: 1.35rem;
  padding: 0 0.35rem;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--accent-contrast);
  font-size: 0.74rem;
  font-weight: 800;
  line-height: 1;
  margin-inline-start: 0.1rem;
}

/* ----------------------------------------- UX-7 compact desktop header --- */
/*
 * Signed in, the desktop row carries the lockup, three destinations as words,
 * four as icons, the view controls and the session - on one line. Nothing may
 * wrap: a second row pushed the account controls under the navigation and made
 * the header twice as tall as the one it replaced. Below 900px the row is not
 * shown at all and the disclosure menu, unchanged, carries every destination.
 *
 * Every rule here is scoped to `.site-header--signed-in`, which the header only
 * carries for a session, so the signed-out header is exactly what it was.
 */

/* Desktop only. `.site-header--signed-in .site-header__bar` outranks the phone
   header's own `.site-header__bar` rules wherever they sit in this file, so an
   unconditional rule here replaced the phone grid's gap too - at 320px it moved
   the lockup off centre and scrolled an English page sideways. Everything that
   shapes the desktop row therefore lives above the menu breakpoint. */
@media (min-width: 901px) {
  .site-header--signed-in .site-header__bar {
    flex-wrap: nowrap;
    gap: 1rem;
  }

  /* The words never shrink below themselves. If the row ever runs out of room
     it has to show as overflow a measurement can see - never as a label
     quietly sliding under the icons beside it. */
  .site-header--signed-in .site-nav {
    flex: 1 0 auto;
  }

  .site-header--signed-in .site-nav ul {
    flex-wrap: nowrap;
  }

  .site-header--signed-in .site-nav a {
    white-space: nowrap;
    padding-inline: 0.65rem;
  }

  /* A username is the one thing on the row whose length nobody chose. It is
     capped with an ellipsis so a long one cannot push the row wide; the full
     name stays in the markup, which is what assistive technology reads. */
  .site-header--signed-in .session-user__name {
    display: inline-block;
    max-inline-size: 8rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
  }
}

.header-actions {
  flex: 0 0 auto;
}

.header-actions ul {
  list-style: none;
  display: flex;
  align-items: center;
  gap: 0.3rem;
  margin: 0;
  padding: 0;
}

.header-action {
  position: relative;
  display: grid;
  place-items: center;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  color: var(--ink-soft);
  transition: background-color 140ms ease, color 140ms ease, border-color 140ms ease;
}

.header-action:hover {
  background: var(--surface-sunken);
  border-color: var(--line);
  color: var(--ink);
  text-decoration: none;
}

/* The current section, the same way the words mark it: accent colour, a soft
   fill and the lit rule underneath. */
.header-action[aria-current="page"] {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: color-mix(in srgb, var(--accent) 35%, transparent);
}

.header-action[aria-current="page"]::after {
  content: "";
  position: absolute;
  inset-inline: 0.65rem;
  bottom: 0.12rem;
  height: 2px;
  border-radius: 2px;
  background: var(--accent);
  box-shadow: var(--glow-soft);
}

.header-action__icon {
  inline-size: 1.3rem;
  block-size: 1.3rem;
}

/* The count sits on the icon's corner, ringed in the header's own colour so it
   reads as a badge rather than as part of the glyph. */
.header-action__count {
  position: absolute;
  inset-block-start: -0.35rem;
  inset-inline-end: -0.4rem;
  min-width: 1.2rem;
  height: 1.2rem;
  padding: 0 0.3rem;
  margin: 0;
  font-size: 0.68rem;
  box-shadow: 0 0 0 2px var(--chrome);
}

/* The icon's name is real text in the link - its accessible name - and it stays
   hidden from sight in every state. A pointer user's hint is the link's own
   `title`, which the browser draws and dismisses; there is deliberately no
   author-built hover or focus tooltip here, because one that cannot be
   dismissed falls short of WCAG 1.4.13. */
.header-action__label {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Tightening, widest first, only where the desktop row is shown. The words and
   icons never go; the room comes from spacing, then from the theme control's
   label (its glyph already says which mode is on), then from the name beside
   the account initial - which stays in the markup for assistive technology. */
@media (min-width: 901px) and (max-width: 1280px) {
  .site-header--signed-in .site-header__bar {
    gap: 0.8rem;
  }

  .site-header--signed-in .site-nav a {
    padding-inline: 0.6rem;
  }

  .site-header--signed-in .theme-toggle [data-theme-label] {
    display: none;
  }
}

@media (min-width: 901px) and (max-width: 1120px) {
  /* Below the shell's own width the bar would otherwise run from screen edge
     to screen edge - its vertical padding shorthand leaves no inline padding -
     and the lockup would sit against the glass. The room for this padding is
     found in the controls below, not taken from the lockup or the words. */
  .site-header--signed-in .site-header__bar {
    gap: 0.55rem;
    padding-inline: 1rem;
  }

  .site-header--signed-in .site-nav ul {
    gap: 0;
  }

  .site-header--signed-in .site-nav a {
    padding-inline: 0.5rem;
  }

  .header-actions ul {
    gap: 0.15rem;
  }

  .header-action {
    inline-size: 2.25rem;
    block-size: 2.25rem;
  }

  .site-header--signed-in .session-actions {
    gap: 0.4rem;
  }

  .site-header--signed-in .control-cluster .control {
    padding-inline: 0.5rem;
  }

  .site-header--signed-in .session-actions .btn--small {
    padding-inline: 0.55rem;
  }

  .site-header--signed-in .session-user {
    padding: 0.25rem;
  }

  .site-header--signed-in .session-user__name {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* The narrowest desktop row, just above the width where the menu takes over:
   the words get a touch smaller rather than any of them leaving. */
@media (min-width: 901px) and (max-width: 1000px) {
  .site-header--signed-in .site-header__bar {
    gap: 0.45rem;
  }

  .site-header--signed-in .site-nav a {
    padding-inline: 0.42rem;
    font-size: 0.88rem;
  }
}

/* UX-8A. A fourth word on the signed-in row - Tutorials, drawn only when the page
   tree offers a tutorial index - is paid for by the same ladder: spacing first,
   then the theme control's label. Every rule is scoped with `:has()` to a row that
   really carries four words, so a site without that index keeps the UX-7 row
   exactly as it was. The widths between 1001px and 1280px already fit four. */
@media (min-width: 1281px) {
  .site-header--signed-in:has(.site-nav li:nth-child(4)) .site-header__bar {
    gap: 0.8rem;
  }

  .site-header--signed-in:has(.site-nav li:nth-child(4)) .site-nav a {
    padding-inline: 0.55rem;
  }

  .site-header--signed-in:has(.site-nav li:nth-child(4)) .theme-toggle [data-theme-label] {
    display: none;
  }
}

@media (min-width: 901px) and (max-width: 1000px) {
  .site-header--signed-in:has(.site-nav li:nth-child(4)) .site-header__bar {
    gap: 0.3rem;
  }

  .site-header--signed-in:has(.site-nav li:nth-child(4)) .site-nav a {
    padding-inline: 0.32rem;
    font-size: 0.85rem;
  }

  .site-header--signed-in:has(.site-nav li:nth-child(4)) .header-actions ul {
    gap: 0.05rem;
  }

  .site-header--signed-in:has(.site-nav li:nth-child(4)) .header-action {
    inline-size: 2.1rem;
    block-size: 2.1rem;
  }
}

/* ------------------------------------------------- disclosure navigation -- */
/*
 * The narrow-viewport menu is a <details> element. No script, no focus trap to
 * get wrong, no state to lose: the browser already knows how to open and close
 * a disclosure and how to tell a screen reader that it did.
 */

.nav-disclosure {
  display: none;
  position: relative;
}

.nav-disclosure > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.8rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  color: var(--ink);
  font-weight: 700;
  font-size: 0.9rem;
}

.nav-disclosure > summary::-webkit-details-marker {
  display: none;
}

.nav-disclosure > summary:hover {
  border-color: var(--accent);
}

/* Anchored to the logical start, which is the edge the button it belongs to
   now sits on: right in Persian, left in English, one rule for both. */
.nav-disclosure__panel {
  position: absolute;
  inset-inline-start: 0;
  top: calc(100% + 0.5rem);
  min-width: 15rem;
  padding: 0.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
  box-shadow: var(--shadow-lg);
  z-index: 40;
}

.nav-disclosure__panel ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.nav-disclosure__panel a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.55rem 0.7rem;
  border-radius: var(--radius);
  color: var(--ink-soft);
  font-weight: 600;
}

.nav-disclosure__panel a:hover,
.nav-disclosure__panel a[aria-current="page"] {
  background: var(--accent-soft);
  color: var(--accent);
  text-decoration: none;
}

/* Signing out sits in the same menu as the destinations but is not one of
   them, so it reads like them and is separated from them. It is a submit
   button because the form it submits is the only correct way to end a
   session; styling it as a menu row is presentation and changes nothing
   about that.

   Hidden until the width at which the header's own sign-out goes away. The two
   are one control with two homes, never two controls: a customer should not be
   able to open this menu and find a second way to do what the button beside it
   already does. The pairing is asserted, because a rule here and a rule three
   hundred lines below is exactly the kind of relationship that rots. */
.nav-disclosure__signout {
  display: none;
  margin-top: 0.35rem;
  padding-top: 0.35rem;
  border-top: 1px solid var(--line);
}

.nav-disclosure__signout form {
  margin: 0;
}

.nav-disclosure__action {
  display: block;
  width: 100%;
  padding: 0.55rem 0.7rem;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink-soft);
  font: inherit;
  font-weight: 600;
  text-align: start;
  cursor: pointer;
}

.nav-disclosure__action:hover {
  background: var(--accent-soft);
  color: var(--accent);
}

/* -------------------------------------------------------------- section --- */

.section {
  padding-block: 3rem;
}

.section--tight {
  padding-block: 2rem;
}

/* Depth, not a rule. A band sits on a slightly different ground and is separated
   by a soft edge, which reads as a change of place rather than a divider. */
.band {
  position: relative;
  background: var(--band);
}

.band::before,
.band::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  height: 1px;
  background: var(--hairline-soft);
}

.band::before {
  top: 0;
}

.band::after {
  bottom: 0;
}

.section__head {
  max-width: 44rem;
  margin-bottom: 1.6rem;
}

/* A head with something on the far side of it - a link to the fuller version of
   whatever the section is showing. `space-between` and not a float, so the
   arrangement mirrors itself between Persian and English. */
.section__head--split {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  max-width: none;
}

.section__head--centred {
  max-width: 44rem;
  margin-inline: auto;
  text-align: center;
}

.section__link {
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--accent);
  white-space: nowrap;
}

.section__head .eyebrow {
  margin-bottom: 0.7rem;
}

.section__head h2 {
  margin-bottom: 0.45rem;
}

.section__head p {
  color: var(--ink-soft);
  margin: 0;
}

.shell-wide {
  max-width: var(--shell-width-wide);
  margin-inline: auto;
  padding-inline: 1rem;
}

/* ----------------------------------------------------------------- hero --- */
/*
 * UX-2. The cinematic first fold.
 *
 * The artwork is a brand *value*. The core decides the shape of the fold - how
 * tall it is, where the copy sits, how far the picture is dimmed under it - and
 * names no file; every URL lives in the brand stylesheet beside the palette.
 *
 * That placement is also what makes the four theme states work with no script
 * at all. A <picture> element can read `prefers-color-scheme` but cannot read
 * `data-theme`, so it would serve the wrong artwork to a viewer who overrode
 * the operating system - and the alternative, shipping both images and hiding
 * one, downloads a hero nobody sees. Declared as a token, the artwork switches
 * by the same mechanism that already switches the ink, in the same three blocks
 * of the same file, and exactly one image is ever fetched.
 *
 * The picture carries no information - every word, price and action is live
 * HTML over it - so it is decorative, and decorative images belong in CSS.
 */

.hero {
  position: relative;
  overflow: hidden;
  display: grid;
  align-items: end;
  min-height: clamp(30rem, 74vh, 44rem);
  background-color: var(--hero-art-ground);
  background-image: var(--hero-wash);
}

/* The artwork, with the key light behind it as the second layer. Two layers in
   one declaration so an unbranded `none` degrades to the gradient rather than
   to a hole. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--hero-art-narrow), var(--hero-key);
  background-size: cover;
  background-position: var(--hero-art-focus-narrow);
  background-repeat: no-repeat;
  pointer-events: none;
}

/* Readability, as a dimming of the picture rather than a panel behind the
   words. A card here would undo the composition the artwork exists for; the
   gradient is weakest at the top, where the globe is, and strongest at the
   bottom, where the copy is. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--hero-veil-narrow);
  pointer-events: none;
}

@media (min-width: 701px) {
  .hero::before {
    background-image: var(--hero-art-sm), var(--hero-key);
    background-position: var(--hero-art-focus);
  }

  .hero::after {
    background: var(--hero-veil);
  }
}

@media (min-width: 1101px) {
  .hero::before {
    background-image: var(--hero-art), var(--hero-key);
  }
}

.hero__inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--shell-width);
  margin-inline: auto;
  padding: 6rem 1rem 3rem;
}

/* Centred, and that is a direction decision as much as a compositional one: a
   centred column has no opinion about which side the page starts on, so the
   same rule is right in Persian and in English. */
.hero__copy {
  max-width: 46rem;
  margin-inline: auto;
  text-align: center;
}

.hero__copy .eyebrow {
  margin-bottom: 0.9rem;
}

.hero h1 {
  font-size: clamp(2.05rem, 1.25rem + 3.3vw, 3.85rem);
  line-height: 1.28;
  font-weight: 800;
  margin-bottom: 0.85rem;
  text-wrap: balance;
  text-shadow: var(--hero-ink-shadow);
}

.hero__lede {
  font-size: 1.08rem;
  line-height: 1.85;
  color: var(--ink-soft);
  margin: 0 auto 1.6rem;
  max-width: 34rem;
  text-wrap: pretty;
  text-shadow: var(--hero-ink-shadow);
}

.hero__lede p {
  margin: 0 0 0.5rem;
}

.hero__lede p:last-child {
  margin-bottom: 0;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  justify-content: center;
}

/* Larger than an ordinary button: this pair is the whole point of the fold, and
   it also has to be a comfortable target on a phone. */
.hero__actions .btn {
  min-height: 3rem;
  padding-inline: 1.6rem;
  font-size: 1rem;
}

/* The quiet action sits on a photograph, so it needs a surface of its own - an
   outline alone disappears over the bright half of the picture. */
.hero__actions .btn--secondary {
  background: var(--surface-glass);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
}

/* ---------------------------------------------------------- feature grid -- */

.feature-grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  list-style: none;
  margin: 0;
  padding: 0;
}

/* A section that climbs into the band above it. Used for the first fold, where
   the capability cards are meant to read as the near edge of the hero rather
   than as the start of a separate page. */
.section--lifted {
  position: relative;
  z-index: 2;
  margin-top: -3.5rem;
  padding-top: 0;
}

.feature {
  position: relative;
  background: var(--surface-glass);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.4rem 1.3rem 1.3rem;
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  transition: border-color 160ms ease, transform 160ms ease, box-shadow 160ms ease;
}

/* The lit top edge. One gradient hairline per card, which is where the brand's
   two colours meet on an otherwise quiet surface. */
.feature::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 1px;
  background: var(--edge);
  opacity: 0.7;
}

.feature:hover {
  border-color: var(--line-strong);
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

.feature__icon {
  display: grid;
  place-items: center;
  width: 2.7rem;
  height: 2.7rem;
  border-radius: 0.85rem;
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid var(--accent-edge);
  margin-bottom: 0.9rem;
  box-shadow: var(--glow-soft);
}

.feature__icon svg {
  width: 1.35rem;
  height: 1.35rem;
}

.feature h3 {
  margin-bottom: 0.35rem;
}

.feature p {
  color: var(--ink-soft);
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.85;
}

/* --------------------------------------------------------------- pieces --- */

.card {
  position: relative;
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.2rem 1.3rem;
  box-shadow: var(--shadow);
  margin-bottom: var(--gap);
}

.card__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.85rem;
  padding-bottom: 0.7rem;
  border-bottom: 1px solid var(--line);
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.6rem;
  border-radius: var(--radius-pill);
  font-size: 0.8rem;
  font-weight: 700;
  background: var(--surface-sunken);
  color: var(--ink-soft);
  border: 1px solid var(--line-strong);
  white-space: nowrap;
}

.empty {
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  padding: 2.25rem 1.25rem;
  text-align: center;
  color: var(--ink-soft);
  background: var(--surface);
}

.empty__mark {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  margin: 0 auto 0.7rem;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  border: 1px solid var(--accent-edge);
  color: var(--accent);
}

.empty__mark svg {
  width: 1.3rem;
  height: 1.3rem;
}

.empty__title {
  margin: 0 0 0.35rem;
  color: var(--ink);
  font-weight: 700;
}

.empty p {
  margin: 0 auto;
  max-width: 34rem;
}

/* -------------------------------------------------------------- buttons --- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.68rem 1.35rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: var(--accent-fill);
  color: var(--accent-contrast);
  font: inherit;
  font-weight: 700;
  font-size: 0.96rem;
  cursor: pointer;
  text-decoration: none;
  box-shadow: var(--glow);
  transition: filter 140ms ease, transform 140ms ease, box-shadow 140ms ease;
}

.btn:hover {
  filter: brightness(1.08);
  text-decoration: none;
  box-shadow: var(--glow-strong);
}

.btn:active {
  transform: translateY(1px);
}

.btn--secondary {
  background: var(--surface-raised);
  color: var(--ink);
  border-color: var(--line-strong);
  box-shadow: none;
}

.btn--secondary:hover {
  background: var(--surface-sunken);
  border-color: var(--accent);
  color: var(--accent);
  filter: none;
}

.btn--alt {
  background: var(--accent-2-fill);
  color: var(--accent-2-contrast);
  box-shadow: var(--glow-2);
}

.btn--quiet {
  background: transparent;
  color: var(--ink-soft);
  border-color: transparent;
  box-shadow: none;
  padding-inline: 0.6rem;
}

.btn--quiet:hover {
  background: var(--surface-sunken);
  color: var(--ink);
  filter: none;
  box-shadow: none;
}

.btn--small {
  padding: 0.4rem 0.8rem;
  font-size: 0.86rem;
}

.btn--wide {
  width: 100%;
}

/* ----------------------------------------------------------------- form --- */

.form-field label {
  display: block;
  font-weight: 700;
  font-size: 0.92rem;
  margin-bottom: 0.35rem;
  color: var(--ink);
}

.form-field input[type="text"],
.form-field input[type="email"],
.form-field input[type="password"],
.form-field input[type="number"],
.form-field select,
.form-field textarea {
  width: 100%;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  color: var(--ink);
  font: inherit;
  transition: border-color 140ms ease, box-shadow 140ms ease, background-color 140ms ease;
}

.form-field input::placeholder,
.form-field textarea::placeholder {
  color: var(--ink-faint);
}

.form-field input:hover,
.form-field select:hover,
.form-field textarea:hover {
  border-color: var(--line-strong);
  background: var(--surface);
}

.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
  border-color: var(--accent);
  outline: none;
  background: var(--surface);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* ----------------------------------------------------------- auth shell --- */

.auth {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  align-items: stretch;
}

.auth__aside {
  position: relative;
  overflow: hidden;
  background: var(--auth-art-ground);
  padding: 3.5rem 3rem;
  display: flex;
  flex-direction: column;
  /* The words sit at the foot of the picture rather than through the middle of
     it. That is what lets one composition carry both themes and both writing
     directions: the veil below only has to clear a band, not a quadrant, and a
     band has no side to be on. */
  justify-content: flex-end;
  gap: 1.25rem;
}

/* Decorative and absolute, so it is the ground the narrative stands on rather
   than a box in the flow. Hidden from assistive technology by the element that
   renders it - nothing here is said only in the picture. */
.auth__visual {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: var(--auth-art);
  background-size: cover;
  background-position: var(--auth-art-position);
  background-repeat: no-repeat;
  pointer-events: none;
}

.auth__visual::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--auth-art-veil);
}

.auth__narrative {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

/* The faintest ink in the system is calibrated for a flat surface, and this one
   is a photograph. Measured at 3.04:1 over the light artwork - the lockup sits
   higher up the panel than the sentence does, where the veil is deliberately
   still thin - so the tagline takes the next ink up rather than the veil taking
   another layer of opacity the picture would pay for. */
.auth__narrative .brand-lockup__tagline {
  color: var(--ink-soft);
}

.auth__headline {
  font-size: clamp(1.6rem, 1.1rem + 1.9vw, 2.4rem);
  line-height: 1.38;
  font-weight: 700;
  margin: 0;
  max-width: 20ch;
}

.auth__lede {
  color: var(--ink-soft);
  max-width: 30ch;
  margin: 0;
  line-height: 1.95;
}

.auth__panel {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3.5rem 1.75rem;
  background: var(--paper);
  border-inline-start: 1px solid var(--line);
}

.auth__form {
  width: 100%;
  /* Wide enough that a five-field form is a form rather than a receipt, narrow
     enough that a label and its input still read as one unit. */
  max-width: 25.5rem;
}

/* -- the authentication form's own rhythm -------------------------------- */
/*
 * A form is read as a sequence of "label, thing to fill in, and anything you
 * need to know about it". The spacing follows that: tight inside a field so the
 * three parts read as one, looser between fields so the eye can count them.
 *
 * Everything below is driven by classes the shared field partial emits, so it
 * applies to whatever the server sends - three fields today, five when the
 * registration contract grows, in any combination of required and optional.
 */
.form-stack .form-field {
  margin-bottom: 1.15rem;
}

.form-stack .form-field label {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  margin-bottom: 0.35rem;
  font-size: 0.94rem;
}

/* The exception carries the information, so only optional is marked. Quiet
   enough not to compete with the label it belongs to. */
.form-field__optional {
  font-weight: 400;
  font-size: 0.78rem;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  /* Not `--ink-faint`, which measures 4.19:1 on the light panel and is the
     right weight only on a surface this form does not have. `--ink-soft` is
     6.99:1 here and still a clear step down from the label beside it. */
  color: var(--ink-soft);
}

/*
 * Password rules arrive from Django as a <ul> and there are four of them. Left
 * as body copy they were the tallest thing on the registration page and read
 * as prose nobody finishes. This makes them a scannable list: smaller, tighter,
 * and visually subordinate to the field they describe.
 *
 * Every rule the validators produce is still rendered. Nothing is truncated,
 * collapsed behind a control, or summarised - the requirements are the server's
 * and this only decides how they look.
 */
.form-field__help {
  margin-top: 0.4rem;
  /* The same reason as the optional marker above: password rules are the one
     thing on this page a reader may genuinely have to work through, so they may
     not be the one thing that misses AA. */
  color: var(--ink-soft);
  font-size: 0.82rem;
  line-height: 1.65;
}

.form-field__help ul {
  margin: 0;
  padding-inline-start: 1.05rem;
}

.form-field__help li + li {
  margin-top: 0.12rem;
}

.form-stack .errorlist {
  margin-top: 0.4rem;
  font-size: 0.85rem;
  line-height: 1.6;
}

/*
 * An invalid field is marked on its edge, not only in the words below it, so a
 * long form does not have to be read to find the one thing that went wrong.
 *
 * The type selectors are not decoration. The base input rule is
 * `.form-field input[type="email"]` and friends - a class, a type and an
 * attribute - so a plain `.form-field--invalid input` is a weaker selector and
 * loses to it. That is why the red border never appeared before: the rule
 * existed and was simply outranked. Matching the base rule's shape is what makes
 * it apply.
 */
.form-field--invalid input[type="text"],
.form-field--invalid input[type="email"],
.form-field--invalid input[type="password"],
.form-field--invalid input[type="number"],
.form-field--invalid input[type="tel"],
.form-field--invalid select,
.form-field--invalid textarea {
  border-color: var(--danger);
}

.form-stack .form-actions {
  margin-top: 1.4rem;
}

/* The recovery route: close enough to the button to be found while a failed
   sign-in is still on screen, quiet enough not to compete with it. */
.form-stack__aside {
  margin-top: 0.8rem;
}

/*
 * UX-3C. The outcome of a step, on the pages that have one instead of a form.
 *
 * Deliberately a mark and not a card. Recovery ends on pages that are a heading,
 * a sentence and a button, and those read as ordinary body copy however
 * important they are - a customer who has just changed their password should not
 * have to read to find out whether it worked. A single shape above the heading
 * is enough to answer that at a glance.
 *
 * The shape carries the meaning, not the colour: a tick and a warning triangle
 * are different outlines, the heading beside them says the same thing in words,
 * and the element itself carries a visually-hidden sentence. Nothing here is the
 * only way to know what happened.
 */
/* Scoped through `.auth__form` throughout, because these are `<p>` elements and
   `.auth__form > p` already claims a colour and a margin at (0,1,1) - a bare
   `.auth-state` would be declared and then quietly outranked, which is the same
   trap the invalid-field border fell into. */
.auth__form .auth-state {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  margin: 0 0 1rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  color: var(--ink-soft);
}

.auth__form .auth-state svg {
  inline-size: 1.25rem;
  block-size: 1.25rem;
}

.auth__form .auth-state--success {
  border-color: var(--ok);
  background: var(--ok-tint);
  color: var(--ok);
}

.auth__form .auth-state--danger {
  border-color: var(--danger);
  background: var(--danger-tint);
  color: var(--danger);
}

/* The practical aside on the "check your email" step: true whether or not
   anything was sent, which is the only kind of advice that page may give. */
.auth__form .auth-note {
  margin-top: -1.1rem;
  color: var(--ink-soft);
}

.auth__form h1 {
  font-size: 1.7rem;
  margin-bottom: 0.4rem;
}

.auth__form > p {
  color: var(--ink-soft);
  margin-bottom: 1.6rem;
}

/* One action, the width of the form it completes. A panel whose only job is to
   be filled in should not make the reader look for the button that finishes it. */
.auth__submit {
  width: 100%;
  justify-content: center;
  min-height: 2.9rem;
}

/* The panel's secondary links: "forgot your password", "create an account",
   "back to the site" - every text link a signed-out visitor can follow from
   here. Scoped to the form column rather than to `.auth`, which would also
   catch the brand lockup: that is an <a> too, and it is deliberately ink
   coloured. `:not(.btn)` leaves the one anchor that is dressed as a button
   alone, since it carries its own fill and its own contrast with it. */
.auth__form a:not(.btn) {
  color: var(--auth-link);
}

.auth__alt {
  margin-top: 1.4rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--line);
  color: var(--ink-soft);
  font-size: 0.92rem;
}

/* -------------------------------------------------------- dashboard ------- */

.dash-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
  padding-bottom: 1.1rem;
  border-bottom: 1px solid var(--line);
}

.dash-head h1 {
  margin: 0;
}

.dash-head p {
  color: var(--ink-soft);
  margin: 0.25rem 0 0;
}

.stat-grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  list-style: none;
  margin: 0 0 var(--gap);
  padding: 0;
}

.stat {
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.1rem 1.2rem;
}

.stat__label {
  display: block;
  font-size: 0.82rem;
  color: var(--ink-faint);
  margin-bottom: 0.35rem;
}

.stat__value {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 800;
  line-height: 1.35;
  font-variant-numeric: tabular-nums;
}

.stat__unit {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink-faint);
  margin-inline-start: 0.25rem;
}

.stat--accent .stat__value {
  color: var(--accent);
}

/* ------------------------------------------------ UX-4 customer dashboard -- */
/*
 * The signed-in control centre. Everything below is layout, rhythm and veil -
 * no hue, no file path, no brand name - so a deployment that supplies no
 * artwork still gets this dashboard rather than a broken one.
 *
 * Two axes decide where things sit, and they are deliberately different:
 *
 *   * **Content** is placed logically. The summary row and the content grid use
 *     `inline-start`/`inline-end`, so Persian reads them from the right and
 *     English from the left, and neither is a mirror somebody has to maintain.
 *   * **Artwork regions** are placed physically. The hero picture has a
 *     character at its left and a city at its right; those do not swap when the
 *     language does, so the copy that has to stay off the character's face is
 *     pinned with a physical margin while its *alignment* still follows the
 *     language. Mirroring the composition instead would put the words over the
 *     figure in one of the two languages.
 */

/* The hero renders through `shell_lead`, outside `<main class="page">`, so it is
   full-bleed without the page's width fighting it. */
.dash-hero {
  position: relative;
  isolation: isolate;
  background-color: var(--dashboard-hero-ground);
  border-bottom: 1px solid var(--dashboard-hero-edge);
  overflow: hidden;
}

/* The picture and the veil are two layers rather than one shorthand, so a brand
   can change either without restating the other. Both are pseudo-elements: the
   artwork never enters the accessibility tree, and nothing here is an <img> a
   screen reader has to be told to ignore. */
.dash-hero::before,
.dash-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.dash-hero::before {
  background-image: var(--dashboard-hero-art);
  background-size: cover;
  background-position: var(--dashboard-hero-position);
  background-repeat: no-repeat;
  z-index: -2;
}

.dash-hero::after {
  background: var(--dashboard-hero-veil);
  z-index: -1;
}

.dash-hero__inner {
  /* The same measure and gutter `.page` uses, so the hero's words line up with
     the cards below it rather than starting at a different edge. */
  max-width: var(--shell-width);
  margin: 0 auto;
  padding: clamp(1.75rem, 1rem + 2.4vw, 3rem) 1rem;
  /* The band's height is the artwork's job to fill and the copy's job not to
     exceed. A minimum rather than a fixed height: a long welcome in either
     language grows the band instead of being clipped by it. */
  min-block-size: clamp(18rem, 13rem + 9vw, 22.5rem);
  display: flex;
  align-items: center;
}

/* Physical, and the comment at the top of this section is why: the quiet part of
   the picture is on the right in both languages, so the words stay there in both
   languages. Only their alignment turns around. */
.dash-hero__copy {
  inline-size: min(100%, 34rem);
  margin-left: auto;
  margin-right: 0;
  text-align: start;
}

.dash-hero__eyebrow {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--dashboard-accent-text);
  margin-block-end: 0.6rem;
}

.dash-hero__title {
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 1.2rem + 2.2vw, 2.9rem);
  font-weight: 800;
  line-height: 1.3;
  margin: 0 0 0.75rem;
}

/* The second half of the greeting, lit the way the rest of the product lights a
   brand word. The customer's name stays in ordinary ink: this is a welcome, not
   an identity banner, and the name is not the part worth colouring. */
.dash-hero__accent {
  color: var(--dashboard-accent-text);
  /* The two words are one phrase; a customer with a long name should push the
     whole greeting onto the next line rather than split it down the middle. */
  white-space: nowrap;
}

.dash-hero__lede {
  color: var(--ink-soft);
  line-height: 1.9;
  margin: 0 0 1.4rem;
  max-inline-size: 44ch;
}

.dash-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
}

/* -- the three summaries ---------------------------------------------------- */

.dash-summary {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gap);
  margin-block-end: var(--gap);
}

/*
 * One card. The whole rectangle is the target, but there is exactly one link in
 * it: the heading's own anchor, stretched over the card by a pseudo-element. A
 * nested "read more" would announce a second, less useful name for the same
 * destination, and a click handler on the card would put a capability in
 * JavaScript, which this surface does not do.
 */
.dash-card {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.35rem 1.4rem;
  background: var(--surface-raised);
  background-image: var(--dashboard-card-glow);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  transition: border-color 140ms ease, transform 140ms ease, box-shadow 140ms ease;
}

.dash-card:hover {
  border-color: var(--accent-edge);
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

.dash-card__body {
  min-inline-size: 0;
  flex: 1 1 auto;
}

.dash-card__label {
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--ink-soft);
  margin: 0 0 0.3rem;
}

/* The heading carries the link, so the card's accessible name is the label a
   sighted reader sees rather than a chevron nobody can name. */
.dash-card__label a {
  color: inherit;
  text-decoration: none;
}

.dash-card__label a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.dash-card__label a:hover {
  color: var(--ink);
}

/* The focus ring belongs to the card, not to the few words of the heading:
   the stretched anchor is the size of the label, and a ring drawn around that
   would point at the wrong rectangle. */
.dash-card:has(.dash-card__label a:focus-visible) {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.dash-card__label a:focus-visible {
  outline: none;
}

.dash-card__value {
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 0.9rem + 0.8vw, 1.5rem);
  font-weight: 800;
  line-height: 1.35;
  margin: 0;
  overflow-wrap: anywhere;
}

.dash-card__value--numeric {
  font-variant-numeric: tabular-nums;
}

.dash-card__note {
  font-size: 0.82rem;
  color: var(--ink-soft);
  line-height: 1.6;
  margin: 0.35rem 0 0;
}

/* Icon and affordance sit at the end of the card in both languages, which puts
   them where the approved composition has them in Persian and mirrors cleanly
   in English. Both are decoration; neither carries meaning the words do not. */
.dash-card__aside {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex: 0 0 auto;
}

.dash-card__chevron {
  inline-size: 1.75rem;
  block-size: 1.75rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink-soft);
}

.dash-card__chevron svg {
  inline-size: 0.9rem;
  block-size: 0.9rem;
  /* The glyph points along the reading direction, so it turns around with the
     language instead of pointing back the way the reader came. */
  transform: scaleX(1);
}

[dir="rtl"] .dash-card__chevron svg {
  transform: scaleX(-1);
}

.dash-card__icon {
  inline-size: 3.1rem;
  block-size: 3.1rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--dashboard-icon-ring);
  border: 1px solid var(--accent-edge);
  color: var(--accent);
}

.dash-card__icon svg {
  inline-size: 1.45rem;
  block-size: 1.45rem;
}

/* Each summary keeps its own hue so the row reads as three things rather than
   one repeated thing - the same restraint the approved composition uses. */
.dash-card--services .dash-card__icon {
  color: var(--accent-2);
  border-color: var(--accent-2);
}

.dash-card--notifications .dash-card__icon {
  color: var(--info);
  border-color: var(--info);
}

/* -- the content grid ------------------------------------------------------- */

/*
 * The anchor first. In Persian that puts My Services under the reader's eye
 * where the page starts, and in English it lands on the left - the same
 * relationship, read from the other end. Named areas rather than nested
 * columns, because the anchor's height depends on what it is holding and the
 * two cases want the three panels arranged differently.
 *
 * Areas are placed by grid column, which follows the writing direction, so the
 * anchor sits at the reading edge in both languages without a mirrored rule.
 */
.dash-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  grid-template-areas:
    "services orders"
    "services support";
  gap: var(--gap);
  align-items: start;
}

.dash-panel--services {
  grid-area: services;
}

.dash-panel--orders {
  grid-area: orders;
}

.dash-support {
  grid-area: support;
}

/*
 * With services owned, the anchor holds two counts instead of the premium empty
 * state, so it is the shortest panel on the page rather than the tallest. Left
 * in its own column it would sit at the top of a mostly empty one while orders
 * and support ran on beside it - most of a screen of nothing, next to a full
 * column.
 *
 * So it spans the top instead and the other two share the row underneath. The
 * hierarchy is unchanged: the anchor is still first, still the widest thing on
 * the page, and still the panel the eye lands on.
 */
.dash-grid--compact-anchor {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-areas:
    "services services"
    "orders   support";
}

.dash-panel {
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.35rem 1.4rem 1.5rem;
  box-shadow: var(--shadow);
  min-inline-size: 0;
}

.dash-panel__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  margin-block-end: 1.1rem;
}

.dash-panel__head h2 {
  font-size: 1.15rem;
  margin: 0;
}

.dash-panel__more {
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--dashboard-accent-text);
}

/* -- the anchor's counts ---------------------------------------------------- */

/*
 * The two figures the service projection owns, at the weight a panel spanning
 * the page needs. `auto-fit` rather than a fixed two: the row is the same shape
 * whether it holds these two or a later, honestly-sourced third, and it becomes
 * a single column on a phone without a breakpoint of its own.
 */
.dash-stats {
  display: grid;
  /* 8rem, so two counts still sit side by side inside a 320px panel rather than
     becoming two tall boxes holding one digit each. `auto-fit` collapses the
     tracks nothing occupies, so on a wide anchor the pair still fills the row. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 8rem), 1fr));
  gap: 0.75rem;
  margin: 0;
}

.dash-stat {
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 0.95rem 1.1rem;
  min-inline-size: 0;
}

/* `--ink-soft`, not `--ink-faint`: measured on the rendered pixel, the faint ink
   came out at 4.00:1 on the sunken panel in the light theme, which is under AA
   for 13px text. The soft ink is the token the card notes already use beside
   these figures, and it clears it in both themes. */
.dash-stat__label {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-soft);
  margin-block-end: 0.35rem;
}

.dash-stat__value {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem);
  font-weight: 800;
  line-height: 1.15;
  margin: 0;
}

/* The conditional lines under the counts. They wrap onto their own rows rather
   than being squeezed onto one, because each is a sentence and neither is an
   ornament. */
.dash-flags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-block-start: 1rem;
}

.dash-flags .badge {
  white-space: normal;
}

/* -- the empty state -------------------------------------------------------- */

/*
 * A deliberate destination rather than an apology. The dashed edge says "this
 * will hold something" instead of "something is broken", and the artwork sits
 * behind it as a watermark - decorative, painted in CSS, absent from the
 * accessibility tree.
 */
.dash-empty {
  position: relative;
  isolation: isolate;
  text-align: center;
  padding: clamp(1.5rem, 1rem + 2vw, 2.75rem) 1.25rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  background-color: var(--surface-sunken);
  overflow: hidden;
}

.dash-empty::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--dashboard-controller-art);
  background-size: cover;
  background-position: 50% 50%;
  background-repeat: no-repeat;
  opacity: 0.14;
  z-index: -1;
  pointer-events: none;
}

.dash-empty__icon {
  inline-size: 4rem;
  block-size: 4rem;
  margin-inline: auto;
  margin-block-end: 1rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--accent-edge);
  background: var(--dashboard-icon-ring);
  color: var(--accent);
}

.dash-empty__icon svg {
  inline-size: 1.9rem;
  block-size: 1.9rem;
}

.dash-empty__title {
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 0.95rem + 0.7vw, 1.45rem);
  font-weight: 800;
  margin: 0 0 0.6rem;
}

.dash-empty__body {
  color: var(--ink-soft);
  line-height: 1.9;
  margin: 0 auto 1.3rem;
  max-inline-size: 52ch;
}

/* The small variant: the same idea inside a narrow card, where the full
   illustration would be bigger than the space it decorates. */
.dash-empty--compact {
  padding: 1.2rem 1rem;
  text-align: start;
  display: flex;
  align-items: flex-start;
  gap: 0.9rem;
}

/*
 * No `background-image` of its own: it inherits the rule above, so the compact
 * card and the full panel ask for the same file and the browser fetches it once.
 * It used to name the small crop here, which meant an empty dashboard - where
 * both states are on screen together - downloaded two controller pictures at
 * every width, including a desktop that had no use for the small one.
 */
.dash-empty--compact::before {
  opacity: 0.1;
}

.dash-empty--compact .dash-empty__icon {
  inline-size: 2.6rem;
  block-size: 2.6rem;
  margin: 0;
  flex: 0 0 auto;
}

.dash-empty--compact .dash-empty__icon svg {
  inline-size: 1.2rem;
  block-size: 1.2rem;
}

.dash-empty--compact .dash-empty__title {
  font-size: 1rem;
  margin-block-end: 0.3rem;
}

.dash-empty--compact .dash-empty__body {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.75;
}

/* -- notes about what a section will hold later ----------------------------- */

/*
 * Not links. They describe what appears in this panel once the customer owns a
 * service, and the product has no separate page for either - so they stay
 * statements rather than becoming a route that does not exist.
 */
.dash-notes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
  margin-block-start: var(--gap);
}

.dash-note {
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
  padding: 0.95rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-sunken);
}

.dash-note__icon {
  inline-size: 2.4rem;
  block-size: 2.4rem;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink-soft);
}

.dash-note__icon svg {
  inline-size: 1.1rem;
  block-size: 1.1rem;
}

.dash-note__title {
  font-weight: 700;
  font-size: 0.95rem;
  margin: 0 0 0.2rem;
}

.dash-note__body {
  font-size: 0.82rem;
  color: var(--ink-soft);
  line-height: 1.7;
  margin: 0;
}

/* -- rows ------------------------------------------------------------------- */

.dash-rows {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}

.dash-row {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.9rem;
  padding: 0.8rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  transition: border-color 140ms ease;
}

.dash-row:hover {
  border-color: var(--accent-edge);
}

.dash-row__main {
  min-inline-size: 0;
}

.dash-row__title {
  font-weight: 700;
  font-size: 0.94rem;
  margin: 0;
  overflow-wrap: anywhere;
}

.dash-row__title a {
  color: inherit;
  text-decoration: none;
}

.dash-row__title a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.dash-row:has(.dash-row__title a:focus-visible) {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

.dash-row__title a:focus-visible {
  outline: none;
}

.dash-row__meta {
  font-size: 0.8rem;
  color: var(--ink-soft);
  margin: 0.2rem 0 0;
}

.dash-row__end {
  flex: 0 0 auto;
  text-align: end;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 0.9rem;
}

/* -- support ---------------------------------------------------------------- */

.dash-support {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background-color: var(--surface-raised);
  padding: 1.4rem 1.4rem 1.5rem;
  box-shadow: var(--shadow);
}

.dash-support::before,
.dash-support::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.dash-support::before {
  background-image: var(--dashboard-support-art);
  background-size: cover;
  background-position: 50% 40%;
  background-repeat: no-repeat;
  z-index: -2;
}

.dash-support::after {
  background: var(--dashboard-support-veil);
  z-index: -1;
}

.dash-support h2 {
  font-size: 1.15rem;
  margin: 0 0 0.55rem;
}

.dash-support__body {
  color: var(--ink-soft);
  line-height: 1.85;
  font-size: 0.9rem;
  margin: 0 0 1.15rem;
  max-inline-size: 40ch;
}

.dash-support__icon {
  inline-size: 3.4rem;
  block-size: 3.4rem;
  margin-block-end: 0.9rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--info);
  background: var(--dashboard-icon-ring);
  color: var(--info);
}

.dash-support__icon svg {
  inline-size: 1.6rem;
  block-size: 1.6rem;
}

/* -- narrow ----------------------------------------------------------------- */

/*
 * 900px is the artwork handover as well as the layout one, and they are the same
 * number on purpose: below it the hero switches to the crop prepared for a
 * phone, so a narrow viewport never fetches the 1920-wide desktop file it would
 * only ever show a third of.
 */
@media (max-width: 900px) {
  .dash-hero::before {
    background-image: var(--dashboard-hero-art-mobile);
    /* The mobile crop is square and its subject is high in the frame, so it is
       anchored near the top and the words sit on the floor the veil builds. */
    background-position: 50% 8%;
  }

  /* A floor rather than a side wash. With the copy full-width under the
     picture, a gradient that darkened one edge would dim the artwork and still
     leave the words on the bright half. */
  .dash-hero::after {
    background: var(--dashboard-hero-veil-mobile);
  }

  .dash-hero__inner {
    /* Tall enough that the picture is a picture: roughly a third of it is
       artwork before the copy begins. */
    min-block-size: clamp(24rem, 18rem + 26vw, 30rem);
    align-items: flex-end;
    padding-block: 1.25rem 1.75rem;
  }

  /* Full width and back to the reading edge: with no room to sit beside the
     picture, the copy sits under it. */
  .dash-hero__copy {
    inline-size: 100%;
    margin-left: 0;
  }

  .dash-support::before {
    background-image: var(--dashboard-support-art-mobile);
  }

  .dash-summary {
    grid-template-columns: minmax(0, 1fr);
  }

  /* One column, and the contract's narrow order: the anchor, then orders, then
     support. Both desktop arrangements collapse onto the same list, so the
     compact-anchor variant needs no separate rule. */
  .dash-grid,
  .dash-grid--compact-anchor {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "services"
      "orders"
      "support";
  }

  .dash-notes {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Between the two, the summaries stay a row - three narrow cards still read as
   a row of three, and stacking them here would waste a screen that has the
   width for them. */
@media (min-width: 641px) and (max-width: 900px) {
  .dash-summary {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .dash-card {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.7rem;
  }

  .dash-card__aside {
    order: -1;
  }
}

/*
 * Once the summaries stack, the reading order stops being a row and becomes a
 * list - and a list is read top to bottom, so it has to follow the task order
 * the UX-4 contract sets: services, then wallet, then notifications.
 *
 * Done with `order` rather than by moving the markup, because the DOM order is
 * the one the desktop row wants and the one a screen reader announces at every
 * width. Above 640 the cards are still three abreast and keep that order
 * untouched; this applies only where they are stacked. `order` is a flex/grid
 * property and knows nothing about direction, so it behaves the same in both.
 */
@media (max-width: 640px) {
  /* The same handover the hero and the support card make at their own widths:
     below this the empty panels are narrow enough that the small crop covers
     them, so a phone stops fetching a 768px picture to paint a 300px box. Both
     empty states take it together, so it is still one file per page. */
  .dash-empty::before {
    background-image: var(--dashboard-controller-art-small);
  }

  .dash-summary {
    display: grid;
  }

  .dash-card--services {
    order: 1;
  }

  .dash-card--wallet {
    order: 2;
  }

  .dash-card--notifications {
    order: 3;
  }
}

@media (max-width: 480px) {
  .dash-card__icon {
    inline-size: 2.6rem;
    block-size: 2.6rem;
  }

  .dash-card__icon svg {
    inline-size: 1.2rem;
    block-size: 1.2rem;
  }

  .dash-row {
    flex-wrap: wrap;
  }

  .dash-row__end {
    text-align: start;
  }
}

/* The band is decoration; a viewer who asked for less movement keeps the lift
   without the motion. */
@media (prefers-reduced-motion: reduce) {
  .dash-card,
  .dash-row {
    transition: none;
  }

  .dash-card:hover {
    transform: none;
  }
}

/* ------------------------------------- UX-5 catalog, checkout, payment ---- */
/*
 * The commercial path: discovery, one offer, the basket, and what happened to
 * the money. Layout, rhythm and veil only - no hue, no file path, no brand name
 * - so a deployment that supplies no artwork still gets these pages rather than
 * a broken version of somebody else's.
 *
 * The same two axes the dashboard uses, for the same reason. **Content** is
 * placed logically (`inline-start`/`inline-end`, `margin-inline`), so Persian
 * reads it from the right and English from the left with one set of rules.
 * **Artwork regions** are placed physically, because a photograph does not
 * mirror when the language does.
 */

/* A button that owns its line. The summary columns stack their actions, and a
   shrink-wrapped button in a narrow column reads as an afterthought. */
.btn--block {
  display: block;
  inline-size: 100%;
  text-align: center;
}

/* -- the discovery hero ----------------------------------------------------- */

/* Rendered through `shell_lead`, outside `<main class="page">`, so the band
   reaches both screen edges without the centred column fighting it. */
.shop-hero {
  position: relative;
  isolation: isolate;
  background-color: var(--commerce-hero-ground);
  border-block-end: 1px solid var(--commerce-hero-edge);
  overflow: hidden;
}

/* Picture and veil as two layers rather than one shorthand, so a brand can
   change either without restating the other. Both are pseudo-elements: the
   artwork never enters the accessibility tree, and there is no <img> a screen
   reader has to be told to ignore. */
.shop-hero::before,
.shop-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.shop-hero::before {
  background-image: var(--commerce-hero-art);
  background-size: cover;
  background-position: var(--commerce-hero-position);
  background-repeat: no-repeat;
  z-index: -2;
}

.shop-hero::after {
  background: var(--commerce-hero-veil);
  z-index: -1;
}

.shop-hero__inner {
  max-width: var(--shell-width);
  margin: 0 auto;
  padding: clamp(1.75rem, 1rem + 2.4vw, 3rem) 1rem;
  /* Tall enough that the artwork reads as a scene rather than a strip, and a
     minimum rather than a fixed height so a long headline grows the band
     instead of being clipped by it. */
  min-block-size: clamp(13rem, 9.5rem + 10vw, 20rem);
  display: flex;
  align-items: center;
}

.shop-hero__copy {
  inline-size: min(100%, 40rem);
  text-align: start;
}

.shop-hero__eyebrow {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--commerce-accent-text);
  margin-block-end: 0.5rem;
}

.shop-hero__title {
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 1.2rem + 2vw, 2.6rem);
  font-weight: 800;
  line-height: 1.25;
  margin: 0 0 0.7rem;
}

.shop-hero__lede {
  color: var(--ink-soft);
  line-height: 1.9;
  margin: 0;
  max-inline-size: 52ch;
}

/* -- how ordering works ----------------------------------------------------- */

/*
 * An ordered list, and semantically so: these are four steps in a sequence, and
 * the numbers are the list's own meaning rather than decoration. The rendered
 * digit is `aria-hidden` because the list already numbers itself to assistive
 * technology - showing it twice is what a decorative glyph is for.
 */
.shop-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: var(--gap);
  list-style: none;
  margin: 0 0 var(--gap);
  padding: 0;
  counter-reset: none;
}

.shop-step {
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.1rem 1.2rem 1.2rem;
  min-inline-size: 0;
}

.shop-step__index {
  display: grid;
  place-items: center;
  inline-size: 1.9rem;
  block-size: 1.9rem;
  border-radius: 50%;
  background: var(--surface-sunken);
  color: var(--commerce-accent-text);
  font-weight: 800;
  font-size: 0.9rem;
  margin-block-end: 0.7rem;
}

.shop-step__title {
  font-weight: 700;
  margin: 0 0 0.25rem;
}

.shop-step__body {
  color: var(--ink-soft);
  font-size: 0.88rem;
  line-height: 1.7;
  margin: 0;
}

/* -- the offer grid --------------------------------------------------------- */

.shop-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
  gap: var(--gap);
  list-style: none;
  margin: 0;
  padding: 0;
}

/*
 * One card, one link. The whole rectangle is the target, but the only anchor in
 * it is the heading's own, stretched by a pseudo-element - a nested "details"
 * link would announce a second, less useful name for the same destination, and a
 * click handler on the card would put a capability in JavaScript, which this
 * surface does not do.
 */
.shop-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.2rem 1.3rem 1.1rem;
  box-shadow: var(--commerce-card-glow);
  transition: transform 140ms ease, border-color 140ms ease;
  min-inline-size: 0;
}

.shop-card:hover {
  transform: translateY(-2px);
  border-color: var(--line-strong);
}

.shop-card__body {
  flex: 1 1 auto;
  min-inline-size: 0;
}

.shop-card__title {
  font-size: 1.1rem;
  margin: 0 0 0.2rem;
}

.shop-card__title a {
  color: inherit;
  text-decoration: none;
}

.shop-card__title a:hover {
  color: var(--commerce-accent-text);
}

.shop-card__variant {
  color: var(--ink-soft);
  font-size: 0.9rem;
  margin: 0 0 0.4rem;
}

.shop-card__summary {
  /* `--ink-soft`, not `--ink-faint`: measured on the rendered pixel, the faint
     ink comes out at 4.42:1 on these panels in the dark theme and 4.00:1 on the
     daylight one, both under AA for text this size. The soft ink clears in
     both (7.89 and 7.54) and is what the rest of the product uses for a
     secondary line. */
  color: var(--ink-soft);
  font-size: 0.86rem;
  line-height: 1.7;
  margin: 0;
}

.shop-card__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.7rem;
  padding-block-start: 0.9rem;
  border-block-start: 1px solid var(--line);
}

.shop-card__price {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 800;
  margin: 0;
}

/* -- empty states ----------------------------------------------------------- */

/*
 * A destination rather than an apology. The dashed edge says "this will hold
 * something" instead of "something is broken", and the artwork sits behind it as
 * a watermark - decorative, painted in CSS, absent from the accessibility tree.
 */
.shop-empty {
  position: relative;
  isolation: isolate;
  text-align: center;
  padding: clamp(1.75rem, 1.25rem + 2vw, 3rem) 1.25rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  background-color: var(--surface-sunken);
  overflow: hidden;
}

.shop-empty::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--commerce-tiers-art);
  background-size: cover;
  background-position: 50% 50%;
  background-repeat: no-repeat;
  opacity: 0.12;
  z-index: -1;
  pointer-events: none;
}

.shop-empty__icon {
  display: grid;
  place-items: center;
  inline-size: 3.5rem;
  block-size: 3.5rem;
  margin-inline: auto;
  margin-block-end: 0.9rem;
  border-radius: 50%;
  background: var(--surface-raised);
  border: 1px solid var(--line);
  color: var(--commerce-accent-text);
}

.shop-empty__icon svg {
  inline-size: 1.6rem;
  block-size: 1.6rem;
}

.shop-empty__title {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 800;
  margin: 0 0 0.4rem;
}

.shop-empty__body {
  color: var(--ink-soft);
  line-height: 1.8;
  margin: 0 0 1.1rem;
  max-inline-size: 46ch;
  margin-inline: auto;
}

/* -- breadcrumb ------------------------------------------------------------- */

.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin-block-end: 1rem;
}

.crumbs a {
  color: var(--ink-soft);
}

.crumbs__sep {
  color: var(--line-strong);
}

/* -- one offer -------------------------------------------------------------- */

.offer {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: var(--gap);
  align-items: start;
}

.offer__main {
  display: grid;
  gap: var(--gap);
  align-content: start;
  min-inline-size: 0;
}

.offer__head {
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.3rem 1.4rem 1.4rem;
}

.offer__title {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.1rem + 1.4vw, 2.1rem);
  font-weight: 800;
  line-height: 1.3;
  margin: 0 0 0.3rem;
}

.offer__variant {
  color: var(--commerce-accent-text);
  font-weight: 700;
  margin: 0 0 0.7rem;
}

.offer__summary {
  color: var(--ink-soft);
  line-height: 1.9;
  margin: 0;
  max-inline-size: 60ch;
}

.offer__section {
  position: relative;
  isolation: isolate;
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.3rem 1.4rem 1.4rem;
  overflow: hidden;
}

/* The prepared generic tier artwork, as a watermark behind the flow panel. It
   illustrates nothing specific, which is the point: it is the same picture
   whatever the offer is. */
.offer__section--art::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--commerce-tiers-art);
  background-size: cover;
  background-position: 50% 30%;
  background-repeat: no-repeat;
  opacity: 0.14;
  z-index: -2;
  pointer-events: none;
}

.offer__section--art::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--commerce-tiers-veil);
  z-index: -1;
  pointer-events: none;
}

.offer__section-title {
  font-size: 1.05rem;
  margin: 0 0 1rem;
}

.offer__plans {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}

.offer-plan {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
  min-inline-size: 0;
}

/* The one you are looking at. Marked with a border *and* a sentence, so the
   distinction is never carried by colour alone. */
.offer-plan--current {
  border-color: var(--accent-edge);
  background: var(--surface);
}

.offer-plan__body {
  min-inline-size: 0;
}

.offer-plan__name {
  font-weight: 700;
  margin: 0;
}

.offer-plan__note {
  color: var(--ink-soft);
  font-size: 0.82rem;
  margin: 0.15rem 0 0;
}

.offer-plan__price {
  font-weight: 700;
  margin: 0;
  white-space: nowrap;
}

.offer__flow {
  color: var(--ink-soft);
  line-height: 1.9;
  margin: 0;
  padding-inline-start: 1.2rem;
}

.offer__flow li + li {
  margin-block-start: 0.35rem;
}

.offer__aside {
  min-inline-size: 0;
}

.offer-summary {
  position: sticky;
  inset-block-start: 1rem;
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.3rem 1.4rem 1.4rem;
  box-shadow: var(--commerce-card-glow);
}

.offer-summary__title {
  font-size: 1.05rem;
  margin: 0 0 1rem;
}

.offer-summary__rows {
  margin: 0 0 1.1rem;
  display: grid;
  gap: 0.5rem;
}

.offer-summary__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.8rem;
  font-size: 0.9rem;
}

.offer-summary__row dt {
  color: var(--ink-soft);
}

.offer-summary__row dd {
  margin: 0;
  font-weight: 600;
  text-align: end;
  min-inline-size: 0;
}

.offer-summary__label {
  color: var(--ink-soft);
  font-size: 0.82rem;
  margin: 0 0 0.2rem;
  padding-block-start: 0.9rem;
  border-block-start: 1px solid var(--line);
}

.offer-summary__price {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 1.1rem + 1vw, 1.9rem);
  font-weight: 800;
  margin: 0 0 1.1rem;
}

.offer-summary__note {
  color: var(--ink-soft);
  font-size: 0.8rem;
  line-height: 1.7;
  margin: 0.9rem 0 0;
}

/* -- checkout --------------------------------------------------------------- */

.checkout {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: var(--gap);
  align-items: start;
}

.checkout__main {
  display: grid;
  gap: var(--gap);
  align-content: start;
  min-inline-size: 0;
}

.checkout__aside {
  display: grid;
  gap: var(--gap);
  align-content: start;
  min-inline-size: 0;
}

/* A generic panel, shared by checkout and the payment result. Named for what it
   is rather than for where it first appeared, because both use it. */
.panel {
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.25rem 1.35rem 1.4rem;
  box-shadow: var(--shadow);
  min-inline-size: 0;
}

.panel__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  margin-block-end: 1rem;
}

.panel__head h2,
.panel__title {
  font-size: 1.05rem;
  margin: 0 0 0.8rem;
}

.panel__head h2 {
  margin: 0;
}

.panel__more {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--commerce-accent-text);
}

.checkout-lines {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}

.checkout-line {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.7rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
  min-inline-size: 0;
}

.checkout-line__body {
  min-inline-size: 0;
}

.checkout-line__title {
  font-weight: 700;
  margin: 0;
}

.checkout-line__variant {
  color: var(--ink-soft);
  font-size: 0.86rem;
  margin: 0.15rem 0 0;
}

.checkout-line__qty {
  color: var(--warn);
  font-size: 0.82rem;
  margin: 0.3rem 0 0;
}

.checkout-line__end {
  display: grid;
  justify-items: end;
  gap: 0.3rem;
  text-align: end;
}

.checkout-line__price {
  font-weight: 700;
  margin: 0;
  white-space: nowrap;
}

/* A form control that reads as a link, for a destructive-but-reversible action
   that has to be a POST. Still a button: it submits, and it is reachable and
   announced as one. */
.linklike {
  appearance: none;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--ink-soft);
  text-decoration: underline;
  cursor: pointer;
}

.linklike:hover {
  color: var(--ink);
}

.checkout-summary {
  position: sticky;
  inset-block-start: 1rem;
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.25rem 1.35rem 1.4rem;
  box-shadow: var(--commerce-card-glow);
}

.checkout-summary__title {
  font-size: 1.05rem;
  margin: 0 0 1rem;
}

.checkout-summary__rows {
  margin: 0 0 1.1rem;
  display: grid;
  gap: 0.55rem;
}

.checkout-summary__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.8rem;
  font-size: 0.92rem;
}

.checkout-summary__row dt {
  color: var(--ink-soft);
}

.checkout-summary__row dd {
  margin: 0;
  font-weight: 600;
  text-align: end;
}

.checkout-summary__row--credit dd {
  color: var(--ok);
}

.checkout-summary__row--total {
  padding-block-start: 0.7rem;
  border-block-start: 1px solid var(--line);
  font-size: 1.05rem;
}

.checkout-summary__row--total dt {
  color: var(--ink);
  font-weight: 700;
}

.checkout-summary__row--total dd {
  font-family: var(--font-display);
  font-weight: 800;
}

.checkout-coupon {
  padding-block: 0.9rem;
  margin-block-end: 0.9rem;
  border-block: 1px solid var(--line);
}

.checkout-coupon__label {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-soft);
  margin-block-end: 0.35rem;
}

.checkout-coupon__entry {
  display: flex;
  gap: 0.5rem;
  align-items: stretch;
}

.checkout-coupon__input {
  flex: 1 1 auto;
  min-inline-size: 0;
}

.checkout-coupon__applied {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.6rem;
}

/*
 * The checkout's reassurance block, over the prepared security artwork. The
 * sentences are about what this application does - a wallet, a gateway, a ticket
 * form - never about how fast, how reliable or how available any of it is.
 *
 * Not rendered at present: the Product Owner's checkout copy cleanup removed the
 * block from the checkout. The rule stays because it is the core's one use of the
 * brand's `--commerce-secure-art` token (UX5 contract); retiring the token is a
 * separate brand decision.
 */
.checkout-assurance {
  position: relative;
  isolation: isolate;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.2rem 1.3rem;
  background-color: var(--surface-sunken);
  overflow: hidden;
}

.checkout-assurance::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--commerce-secure-art);
  background-size: cover;
  background-position: 50% 35%;
  background-repeat: no-repeat;
  opacity: 0.16;
  z-index: -2;
  pointer-events: none;
}

.checkout-assurance::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--commerce-secure-veil);
  z-index: -1;
  pointer-events: none;
}

.checkout-assurance__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.55rem;
  color: var(--ink-soft);
  font-size: 0.86rem;
  line-height: 1.7;
}

/* -- payment result --------------------------------------------------------- */

/*
 * One block, seven states. The status class only tints an edge and an icon: the
 * words under it say what happened, and every state also carries its own glyph,
 * so nothing here depends on a viewer distinguishing green from amber.
 */
.payres {
  position: relative;
  isolation: isolate;
  text-align: center;
  padding: clamp(1.75rem, 1.25rem + 2vw, 3rem) 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background-color: var(--surface-raised);
  margin-block-end: var(--gap);
  overflow: hidden;
}

.payres__icon {
  display: grid;
  place-items: center;
  inline-size: 4rem;
  block-size: 4rem;
  margin-inline: auto;
  margin-block-end: 1rem;
  border-radius: 50%;
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  color: var(--ink-soft);
}

.payres__icon svg {
  inline-size: 1.9rem;
  block-size: 1.9rem;
}

.payres__title {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.1rem + 1.4vw, 2.1rem);
  font-weight: 800;
  line-height: 1.3;
  margin: 0 0 0.5rem;
}

.payres__lead {
  font-size: 1.02rem;
  line-height: 1.8;
  margin: 0 auto;
  max-inline-size: 56ch;
}

.payres__body {
  color: var(--ink-soft);
  line-height: 1.8;
  margin: 0.6rem auto 0;
  max-inline-size: 56ch;
}

.payres__actions {
  margin: 1.3rem 0 0;
}

/* Funded is the one state that gets the prepared success artwork. It is a
   payment picture and not an activation one, which is also what the copy says. */
.payres--funded::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--commerce-success-art);
  background-size: cover;
  background-position: 50% 35%;
  background-repeat: no-repeat;
  opacity: 0.18;
  z-index: -2;
  pointer-events: none;
}

.payres--funded::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--commerce-success-veil);
  z-index: -1;
  pointer-events: none;
}

.payres--funded,
.payres--settled {
  border-color: var(--ok);
}

.payres--funded .payres__icon,
.payres--settled .payres__icon {
  color: var(--ok);
  border-color: var(--ok);
}

.payres--checking,
.payres--pending,
.payres--awaiting_payment,
.payres--recorded {
  border-color: var(--info);
}

.payres--checking .payres__icon,
.payres--pending .payres__icon,
.payres--awaiting_payment .payres__icon,
.payres--recorded .payres__icon {
  color: var(--info);
  border-color: var(--info);
}

.payres--retryable,
.payres--not_settled,
.payres--payment_uncertain,
.payres--needs_attention {
  border-color: var(--warn);
}

.payres--retryable .payres__icon,
.payres--not_settled .payres__icon,
.payres--payment_uncertain .payres__icon,
.payres--needs_attention .payres__icon {
  color: var(--warn);
  border-color: var(--warn);
}

.payres__total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.8rem;
  padding-block-start: 0.9rem;
  margin-block-start: 0.9rem;
  border-block-start: 1px solid var(--line);
  font-size: 1.05rem;
}

.payres-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: var(--gap);
  align-items: start;
}

.payres-aside {
  display: grid;
  gap: var(--gap);
  align-content: start;
  min-inline-size: 0;
}

.payres-pay__choice {
  margin: 0 0 0.6rem;
}

/*
 * COMMERCE-LIFECYCLE CLC-04 (compact, action-first checkout). The order and
 * payment pages use the same status block in a compact form: a small glyph
 * beside a modest heading, start-aligned, with content-driven height. Scoped to
 * the `--compact` modifier so other `.payres` surfaces (the provider return page)
 * keep their own presentation.
 *
 * Nothing is hidden here: every state keeps every sentence it had - "do not pay
 * again", the Finance and refund explanations - and only the box around them gets
 * smaller. States that warn keep their tone edge and gain a tint, so they still
 * read as the alerts they are.
 */
.payres--compact {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 0.85rem;
  align-items: start;
  text-align: start;
  padding: 0.95rem 1.1rem;
  border-radius: var(--radius);
  border-inline-start-width: 4px;
}

.payres--compact > * {
  grid-column: 2;
}

.payres--compact > .payres__icon {
  grid-column: 1;
  grid-row: 1 / span 4;
  inline-size: 2.25rem;
  block-size: 2.25rem;
  margin: 0.15rem 0 0;
}

.payres--compact .payres__icon svg {
  inline-size: 1.15rem;
  block-size: 1.15rem;
}

.payres--compact .payres__title {
  font-size: clamp(1.1rem, 1.02rem + 0.35vw, 1.3rem);
  line-height: 1.5;
  margin: 0 0 0.2rem;
}

.payres--compact .payres__lead {
  font-size: 0.97rem;
  line-height: 1.75;
  margin: 0;
  max-inline-size: none;
}

.payres--compact .payres__body {
  font-size: 0.93rem;
  line-height: 1.75;
  margin: 0.3rem 0 0;
  max-inline-size: none;
}

.payres--compact .payres__actions {
  margin: 0.65rem 0 0;
}

/* The success artwork belongs to the full-size block; a compact header is a
   status line, not a celebration. */
.payres--compact.payres--funded::before,
.payres--compact.payres--funded::after {
  content: none;
}

.payres--compact.payres--retryable,
.payres--compact.payres--payment_uncertain,
.payres--compact.payres--needs_attention {
  background-color: var(--warn-tint);
}

/* Payment first: the column that holds the payment choice (or the bank
   instruction, or what to do next) comes first in the document - so it leads on
   a phone and for keyboard and screen-reader order - and sits beside the order's
   details on a wide screen. */
.payres-grid--action {
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
}

.payres-primary {
  display: grid;
  gap: var(--gap);
  align-content: start;
  min-inline-size: 0;
}

/* Narrow screens (320px): the checkout's columns may shrink below their content's
   widest unbreakable run instead of widening the page, and a long status badge in an
   unfinished-purchase row or the Orders list's "next step" cell (the CLC-03 action
   partial) wraps instead of pushing the row sideways. Scoped to that partial's
   containers; badges elsewhere keep their single line. */
.checkout__main,
.checkout__aside {
  grid-template-columns: minmax(0, 1fr);
}

.checkout-line .orders-actions .badge,
.orders-table__next .orders-actions .badge {
  white-space: normal;
}

/* An option that is present, named and unavailable. Dimmed rather than removed,
   because a wallet that silently disappears looks like a platform that forgot
   it. */
.payres-pay__choice--off {
  opacity: 0.65;
}

/* -- narrow ----------------------------------------------------------------- */

@media (max-width: 900px) {
  .offer,
  .checkout,
  .payres-grid,
  .payres-grid--action {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Sticky is for a column that scrolls past something. Once everything is one
     column there is nothing to stick beside, and a stuck summary would cover the
     content under it. */
  .offer-summary,
  .checkout-summary {
    position: static;
  }

  .shop-hero__inner {
    min-block-size: clamp(9rem, 7rem + 8vw, 13rem);
  }
}

@media (max-width: 640px) {
  .checkout-line,
  .offer-plan {
    flex-direction: column;
    align-items: stretch;
  }

  .checkout-line__end {
    justify-items: start;
    text-align: start;
  }

  .offer-plan__price,
  .checkout-line__price {
    white-space: normal;
  }
}

@media (prefers-reduced-motion: reduce) {
  .shop-card {
    transition: none;
  }

  .shop-card:hover {
    transform: none;
  }
}

/* ------------------------ UX-6 active services, addresses, renewal -------- */
/*
 * What a customer owns, and the three changes the platform actually supports
 * making to it. Layout, rhythm and veil only - no hue, no file path, no brand
 * name - so a deployment that supplies no artwork gets these pages on plain
 * panels rather than a broken version of somebody else's.
 *
 * The same two axes the dashboard and the shop use, for the same reason.
 * **Content** is placed logically (`inline-start`/`inline-end`,
 * `margin-inline`), so Persian reads it from the right and English from the
 * left with one set of rules. **Artwork regions** are placed physically,
 * because a photograph does not mirror when the language does.
 *
 * Status here is never colour alone. Every badge carries the axis name beside
 * it and the domain's own translated value inside it, so the five axes stay
 * legible without colour vision, in forced-colours mode, and when the artwork
 * behind them fails to load.
 */

/* The quiet tone. The base badge already looks like this; naming it keeps the
   markup symmetrical - every axis emits `badge--<tone>` - so nobody has to
   remember that one of the five is the one without a modifier. */
.badge--neutral {
  background: var(--surface-sunken);
  color: var(--ink-soft);
  border-color: var(--line-strong);
}

/* -- the lead band --------------------------------------------------------- */

/* Rendered through `shell_lead`, outside `<main class="page">`, so the band
   reaches both screen edges without the centred column fighting it. */
.svc-hero {
  position: relative;
  isolation: isolate;
  background-color: var(--services-hero-ground);
  border-block-end: 1px solid var(--services-hero-edge);
  overflow: hidden;
}

/* Picture and veil as two layers rather than one shorthand, so a brand can
   change either without restating the other. Both are pseudo-elements: the
   artwork never enters the accessibility tree, and there is no <img> a screen
   reader has to be told to ignore. */
.svc-hero::before,
.svc-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.svc-hero::before {
  background-image: var(--services-hero-art);
  background-size: cover;
  background-position: var(--services-hero-position);
  background-repeat: no-repeat;
  z-index: -2;
}

.svc-hero::after {
  background: var(--services-hero-veil);
  z-index: -1;
}

.svc-hero__inner {
  max-width: var(--shell-width);
  margin: 0 auto;
  padding: clamp(1.75rem, 1rem + 2.4vw, 3rem) 1rem;
  /* A minimum rather than a fixed height: a long service name in either
     language grows the band instead of being clipped by it. */
  min-block-size: clamp(12rem, 9rem + 9vw, 18rem);
  display: flex;
  align-items: center;
}

/* The detail band is short. The page under it is dense, and a full-height
   picture would push the first fact below the fold on a laptop. It carries the
   brand and the page's name; the summary card under it describes the service.
   SERVICE-DETAIL-COMPACT-01 gives it the brand's creature as a layer of its own,
   above the scene and its veil and below the copy, so the picture can never sit
   on top of a word. */
.svc-hero--detail .svc-hero__inner {
  position: relative;
  z-index: 1;
  min-block-size: clamp(7.5rem, 6rem + 4vw, 10rem);
  padding-block: clamp(1rem, 0.75rem + 1vw, 1.6rem);
}

.svc-hero--detail::before {
  opacity: 0.55;
}

.svc-hero--detail .svc-hero__title {
  font-size: clamp(1.35rem, 1.1rem + 1.1vw, 1.9rem);
  margin-block-end: 0.3rem;
}

.svc-hero--detail .svc-hero__lede {
  font-size: 0.92rem;
  line-height: 1.7;
}

/*
 * The creature: the brand's own artwork, painted from `--services-beast-art` (none in the
 * core, so an unbranded install draws nothing here). It sits at the reading end, opposite the
 * copy, and fades towards it through a mask - a picture that is never under the text. An
 * artwork region is placed physically elsewhere on these pages; this one follows the reading
 * end instead, and is mirrored in a left-to-right page so the creature always faces the copy.
 */
.svc-hero__beast {
  display: none;
}

.svc-hero--detail .svc-hero__beast {
  display: block;
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  inline-size: min(48%, 36rem);
  z-index: 0;
  background-image: var(--services-beast-art);
  background-size: cover;
  background-position: var(--services-beast-position);
  background-repeat: no-repeat;
  opacity: 0.9;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to right, black 45%, transparent);
  mask-image: linear-gradient(to right, black 45%, transparent);
}

html[dir="ltr"] .svc-hero--detail .svc-hero__beast {
  transform: scaleX(-1);
}

.svc-hero__copy {
  inline-size: min(100%, 40rem);
  text-align: start;
}

.svc-hero__eyebrow {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--services-accent-text);
  margin-block-end: 0.5rem;
}

.svc-hero__title {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 1.15rem + 1.9vw, 2.5rem);
  font-weight: 800;
  line-height: 1.25;
  margin: 0 0 0.7rem;
  /* A product name can be long and is not a phrase anyone should read broken
     across a glyph boundary. */
  overflow-wrap: anywhere;
}

.svc-hero__lede {
  color: var(--ink-soft);
  line-height: 1.9;
  margin: 0;
  max-inline-size: 52ch;
}

/* -- the list ------------------------------------------------------------- */

.svc-listhead {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-block-end: var(--gap);
}

.svc-listhead__title {
  font-family: var(--font-display);
  font-size: clamp(1.2rem, 1rem + 0.7vw, 1.55rem);
  font-weight: 800;
  margin: 0;
}

/*
 * The cards sit on the prepared overview scene, at watermark strength. It is
 * scenery rather than illustration: the same picture whatever the services are,
 * carrying none of their meaning, which is why it is allowed to be decorative.
 * Absolutely positioned, so it does not become a grid item.
 */
.svc-grid {
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
  gap: var(--gap);
  list-style: none;
  margin: 0;
  padding: 0;
}

.svc-grid::before,
.svc-grid::after {
  content: "";
  position: absolute;
  inset: calc(var(--gap) * -1);
  border-radius: var(--radius-lg);
  pointer-events: none;
}

.svc-grid::before {
  background-image: var(--services-scene-art);
  background-size: cover;
  background-position: 50% 35%;
  background-repeat: no-repeat;
  opacity: 0.12;
  z-index: -2;
}

.svc-grid::after {
  background: var(--services-scene-veil);
  z-index: -1;
}

.svc-card {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  background: var(--surface-raised);
  background-image: var(--services-card-glow);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.15rem 1.2rem 1.2rem;
  /* Grid children default to `min-width: auto`, which lets a long address or
     product name push the whole column wider than the viewport. */
  min-inline-size: 0;
}

.svc-card__head {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
}

.svc-card__mark {
  display: grid;
  place-items: center;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  flex: 0 0 auto;
  border-radius: var(--radius);
  background: var(--surface-sunken);
  border: 1px solid var(--line-strong);
  color: var(--services-accent-text);
}

.svc-card__mark svg,
.svc-panel__icon svg,
.svc-identity__mark svg,
.svc-help__icon svg {
  inline-size: 1.25rem;
  block-size: 1.25rem;
}

.svc-card__ident {
  flex: 1 1 auto;
  min-inline-size: 0;
}

.svc-card__title {
  font-size: 1.02rem;
  font-weight: 700;
  line-height: 1.4;
  margin: 0;
  overflow-wrap: anywhere;
}

.svc-card__title a {
  color: inherit;
  text-decoration: none;
}

.svc-card__title a:hover {
  text-decoration: underline;
}

.svc-card__variant {
  color: var(--ink-soft);
  font-size: 0.88rem;
  margin: 0.15rem 0 0;
  overflow-wrap: anywhere;
}

/* Beside the name rather than pinned to the far edge. A badge across the card
   from the thing it describes has to be re-associated by eye every time, and at
   card width the gap between them is most of the card. */
.svc-card__name {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

/*
 * Four axes as four labelled rows. A definition list, and semantically so: each
 * is a name and the value the domain gave it. Two columns on a card, one on a
 * phone, and the label never disappears - it is what makes the badge mean
 * something to somebody who cannot see its colour.
 */
.svc-axes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr));
  gap: 0.55rem 0.9rem;
  margin: 0;
}

.svc-axis {
  min-inline-size: 0;
}

.svc-axis dt {
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-block-end: 0.25rem;
}

.svc-axis dd {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}

.svc-card__notice {
  margin: 0;
}

.svc-card__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin-block-start: auto;
  padding-block-start: 0.85rem;
  border-block-start: 1px solid var(--line);
}

.svc-card__since {
  margin: 0;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

/* The same watermark treatment as the grid, so an account with nothing in it
   still looks like part of the product. */
.svc-empty {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  padding: clamp(2rem, 1.5rem + 2vw, 3.25rem) 1.25rem;
  text-align: center;
  background: var(--surface);
}

.svc-empty::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--services-scene-art);
  background-size: cover;
  background-position: 50% 45%;
  background-repeat: no-repeat;
  opacity: 0.12;
  z-index: -1;
  pointer-events: none;
}

.svc-empty__lede {
  font-size: 1.05rem;
  font-weight: 700;
  margin: 0 0 0.35rem;
}

.svc-empty__note {
  color: var(--ink-soft);
  margin: 0 auto 1.1rem;
  max-inline-size: 40ch;
}

/* -- the detail page ------------------------------------------------------ */
/*
 * SERVICE-DETAIL-COMPACT-01. One column of compact surfaces: the summary card, usage beside the
 * DNS servers on a wide screen, the IP panel, the renewal, then history and support. Every rule
 * here is scoped to the detail page's own classes - nothing on the wallet, staff, payment or
 * service-list pages changes with it.
 *
 * The density pass (Product Owner review): a card exists only where a surface is genuinely
 * independent. Inside a panel, facts, readings, IPs and DNS servers are rows and cells divided by
 * hairlines - never a bordered tile around each - and no panel is stretched to its neighbour's
 * height. The renewal choices are the one place equal height is wanted.
 */

.svc-crumbs {
  margin-block-end: 0.6rem;
  font-size: 0.82rem;
}

.svc-crumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  list-style: none;
  margin: 0;
  padding: 0;
  color: var(--ink-soft);
}

/* The crumb link takes the surface's own accent rather than the site-wide link
   colour. Measured rather than assumed: the neon green that reads well on the
   dark ground falls to 3.87:1 as 13.6px text on the daylight page, and the
   brand's darker green is the value the light blocks already substitute for
   exactly this reason. */
.svc-crumbs a {
  color: var(--services-accent-text);
}

.svc-crumbs li + li::before {
  content: "/";
  margin-inline-end: 0.4rem;
  color: var(--ink-soft);
}

.svc-detail,
.svc-detail__main {
  display: grid;
  gap: 0.7rem;
  min-inline-size: 0;
}

.svc-panel {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 0.75rem 0.9rem 0.8rem;
  min-inline-size: 0;
}

.svc-panel--manage {
  background-image: var(--services-card-glow);
}

.svc-panel__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.55rem;
  margin-block-end: 0.5rem;
}

.svc-panel__icon {
  display: grid;
  place-items: center;
  inline-size: 1.7rem;
  block-size: 1.7rem;
  flex: 0 0 auto;
  border-radius: var(--radius);
  background: var(--surface-sunken);
  border: 1px solid var(--line-strong);
  color: var(--services-accent-text);
}

.svc-panel__icon svg {
  inline-size: 1rem;
  block-size: 1rem;
}

.svc-panel__title {
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 800;
  margin: 0;
  flex: 1 1 auto;
  min-inline-size: 0;
}

/* Pushed to the reading end, so the secondary control sits where the eye
   leaves the heading in either direction. */
.svc-panel__action {
  margin-inline-start: auto;
}

.svc-panel__note {
  color: var(--ink-soft);
  font-size: 0.79rem;
  line-height: 1.6;
  margin: 0.45rem 0 0;
}

.svc-panel__stamp,
.svc-panel__empty {
  color: var(--ink-soft);
  font-size: 0.78rem;
  margin: 0;
}

.svc-panel > .svc-panel__stamp:last-child {
  margin-block-start: 0.45rem;
}

.svc-panel .notice {
  margin-block: 0 0.5rem;
}

/* -- the summary card: overview + current entitlement, drawn as one ---------- */

/*
 * Two sections, one surface. The overview and the current entitlement keep their own headings
 * and their own facts (ADR §8.1 - nothing is merged), and the card draws them as one block with
 * a hairline between, so the page opens on a single summary rather than two stacked cards.
 */
.svc-summary-card {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
  background-image: var(--services-card-glow);
  overflow: hidden;
  min-inline-size: 0;
}

.svc-summary-card > .svc-panel {
  border: 0;
  border-radius: 0;
  background-color: transparent;
  padding-block: 0.65rem;
}

.svc-summary-card > .svc-panel + .svc-panel {
  border-block-start: 1px solid var(--line);
}

/* The identity panel carries the prepared detail frame, at watermark strength
   and under a veil. Every figure on top of it is ordinary body text, so the
   picture has to stay well behind the reading contrast rather than merely
   beside it. */
.svc-panel--identity::before,
.svc-panel--identity::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.svc-panel--identity::before {
  background-image: var(--services-frame-art);
  background-size: cover;
  background-position: 50% 30%;
  background-repeat: no-repeat;
  opacity: 0.12;
  z-index: -2;
}

.svc-panel--identity::after {
  background: var(--services-frame-veil);
  z-index: -1;
}

.svc-identity {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45rem 0.65rem;
}

.svc-identity__mark {
  display: grid;
  place-items: center;
  inline-size: 2.1rem;
  block-size: 2.1rem;
  flex: 0 0 auto;
  border-radius: var(--radius);
  background: var(--surface-sunken);
  border: 1px solid var(--line-strong);
  color: var(--services-accent-text);
}

.svc-identity__mark svg {
  inline-size: 1.15rem;
  block-size: 1.15rem;
}

.svc-identity__text {
  flex: 0 1 auto;
  min-inline-size: 0;
}

.svc-identity__title {
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 0.95rem + 0.4vw, 1.25rem);
  font-weight: 800;
  margin: 0;
  overflow-wrap: anywhere;
}

.svc-identity__state {
  flex: 0 0 auto;
}

/* SERVICE-DETAIL-ACTIVATION-HINT-01. One informational line in the identity row's free space,
   between the state and the refresh: plain text in the success token (--ok, which each theme and
   brand already sets), no box, badge or motion. It takes the room the row has and gives way to a
   line of its own when there is not enough, so it never overlaps the state or the button and
   never makes the row taller than one wrapped line. */
.svc-identity__hint {
  flex: 1 1 16rem;
  min-inline-size: 0;
  margin: 0;
  color: var(--ok);
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.5;
  text-align: center;
}

/* The refresh is the summary's quiet secondary action: a small control at the reading end of
   the identity row, never a second primary button. PO-SVC-REFRESH-ORANGE: it takes its colours
   from the --service-refresh-* tokens - a hairline edge, a faint tint and a restrained glow, never
   a filled block - so a brand can accent this one control. Only this control: .btn--quiet
   elsewhere is untouched. Focus keeps the global :focus-visible ring. */
.svc-refresh .btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: var(--service-refresh-text);
  background: var(--service-refresh-tint);
  border-color: var(--service-refresh-edge);
  box-shadow: var(--service-refresh-glow);
}

.svc-refresh .btn:hover,
.svc-refresh .btn:active {
  color: var(--service-refresh-text-hover);
  background: var(--service-refresh-tint-hover);
  border-color: var(--service-refresh-edge-hover);
  box-shadow: var(--service-refresh-glow-hover);
}

.svc-refresh__icon {
  inline-size: 0.95rem;
  block-size: 0.95rem;
  color: var(--service-refresh-accent);
}

.svc-refresh .btn:hover .svc-refresh__icon,
.svc-refresh .btn:active .svc-refresh__icon {
  color: var(--service-refresh-accent-hover);
}

/*
 * The axes that have something to say, as one wrapping row of labelled values. Every axis keeps
 * its own label, so the row reads without colour.
 */
.svc-overview__status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 1rem;
  margin: 0.5rem 0 0;
  padding-block-start: 0.45rem;
  border-block-start: 1px solid var(--line);
}

.svc-overview__axis {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  min-inline-size: 0;
}

.svc-overview__axis dt {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ink-soft);
}

.svc-overview__axis dd {
  margin: 0;
  font-size: 0.84rem;
  overflow-wrap: anywhere;
}

.svc-overview__axis .svc-usage__note {
  display: inline;
  margin-inline-start: 0.35rem;
}

.svc-panel--entitlement .svc-panel__head {
  margin-block-end: 0.35rem;
}

.svc-entitlement__title {
  font-size: 0.8rem;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ink-soft);
}

/*
 * Facts as a definition list. The `--strip` variant is the one the summary, the pending renewal
 * and the usage panel use: one row of labelled values divided by hairlines - never a bordered
 * tile around each - that wraps into further rows on a narrower panel.
 *
 * Each fact draws its divider on its reading-start edge and its top, pulled one pixel outside its
 * own box, and the strip clips that pixel. So the first fact of every line, and every fact of the
 * first line, lose theirs and only the dividers *between* facts remain, however the row wraps.
 * The strip reaches into its container's padding by the facts' own inset, so the first label
 * lines up with the heading above it.
 */
.svc-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: 0.6rem 0.75rem;
  margin: 0;
}

.svc-facts--strip {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  margin-inline: -0.75rem;
  overflow: hidden;
}

/* Short labelled values in rows and cells: a tighter line than the page's reading text, which is
   set for paragraphs. */
.svc-fact,
.svc-usage__figure,
.svc-address,
.svc-renewal,
.svc-choice {
  line-height: 1.5;
}

.svc-fact {
  min-inline-size: 0;
}

.svc-facts--strip > .svc-fact {
  flex: 1 1 8.5rem;
  margin-block-start: -1px;
  margin-inline-start: -1px;
  padding: 0.3rem 0.75rem;
  border-block-start: 1px solid var(--line);
  border-inline-start: 1px solid var(--line);
}

.svc-facts--strip > .svc-fact--wide {
  flex: 2 1 13rem;
}

.svc-fact dt {
  font-size: 0.69rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-block-end: 0.15rem;
}

.svc-fact dd {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 700;
  overflow-wrap: anywhere;
}

/* A renewal the service platform has accepted but not yet started: its own strip under a dashed
   hairline, on a faint second-accent ground - set apart from the current entitlement, never
   drawn as it, and never in alarm colour. */
.svc-pending-renewal {
  display: grid;
  gap: 0.35rem;
  margin-block-start: 0.6rem;
  padding: 0.5rem 0.75rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent-2) 6%, transparent);
  min-inline-size: 0;
}

.svc-pending-renewal p {
  margin: 0;
}

.svc-pending-renewal__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.6rem;
}

.svc-form__title {
  font-size: 0.88rem;
  font-weight: 700;
  margin: 0;
}

/* -- usage beside the DNS servers ------------------------------------------ */

/*
 * Two sibling panels on one row - usage beside the DNS servers, and the IPs beside adding one -
 * in the same 60/40 rhythm, so together they span exactly the summary's width. Each panel is as
 * tall as its own content: equal height is not a goal here, and a short panel ends where its
 * content ends rather than growing an empty lower half to match. A panel alone in its row (a
 * customer who may not add an IP) takes the whole row.
 */
.svc-pair {
  display: grid;
  gap: 0.7rem;
  align-items: start;
  min-inline-size: 0;
}

@media (min-width: 64rem) {
  .svc-pair {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  }

  .svc-pair > :only-child {
    grid-column: 1 / -1;
  }
}

/* -- usage and cycle (A2) ------------------------------------------------- */

/* The ring beside the three readings. Without a percentage to draw (an unstated figure) the
   readings simply take the whole row. */
.svc-usage-meter {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 1rem;
  min-inline-size: 0;
}

.svc-usage-meter > .svc-usage:only-child {
  grid-column: 1 / -1;
}

/*
 * The ring: two circles whose circumference is 100 path units, so the stroke dash is the
 * percentage. Drawn by presentation attributes and this stylesheet - there is no inline style for
 * the Content-Security-Policy to refuse - and hidden from assistive technology, which reads the
 * native <progress> instead. Physical rotation on purpose: a gauge does not mirror with language.
 */
.svc-ring {
  position: relative;
  inline-size: 5.5rem;
  block-size: 5.5rem;
  flex: 0 0 auto;
}

.svc-ring__svg {
  inline-size: 100%;
  block-size: 100%;
  transform: rotate(-90deg);
}

.svc-ring__track,
.svc-ring__value {
  fill: none;
  stroke-width: 3.6;
}

.svc-ring__track {
  stroke: var(--line);
}

.svc-ring__value {
  stroke: var(--services-accent-text);
  stroke-linecap: butt;
}

.svc-ring__figure {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--ink);
  direction: ltr;
  unicode-bidi: isolate;
}

/* Three readings of one thing, as rows divided by hairlines: the label at the reading start, the
   figure at the end. A list, so it stacks on a phone without a table to re-explain. */
.svc-usage {
  display: grid;
  list-style: none;
  margin: 0;
  padding: 0;
  min-inline-size: 0;
  max-inline-size: 26rem;
}

.svc-usage__figure {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.2rem 0.6rem;
  min-inline-size: 0;
  padding-block: 0.3rem;
}

.svc-usage__figure + .svc-usage__figure {
  border-block-start: 1px solid var(--line);
}

.svc-usage__label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink-soft);
  margin: 0;
}

.svc-usage__value {
  font-family: var(--font-display);
  font-size: 0.98rem;
  font-weight: 800;
  margin: 0;
  overflow-wrap: anywhere;
}

/* The bar's semantics without the bar: the ring is the picture, and this keeps the native
   progressbar in the accessibility tree with its true `aria-valuetext`. */
.svc-usage__meter {
  appearance: none;
  -webkit-appearance: none;
}

/* The ring is never the only signal: the percentage is written out beneath it. */
.svc-usage__percent {
  color: var(--ink-soft);
  font-size: 0.78rem;
  margin: 0.35rem 0 0;
}

/* The cycle and measurement facts under the readings, set off by one hairline. */
.svc-usage__facts {
  margin-block-start: 0.5rem;
  margin-inline: -0.6rem;
  border-block-start: 1px solid var(--line);
}

/* Five short facts in a part-width panel: narrower cells and a smaller figure, so they share
   one row on a desktop - a date and its time included. The cycle's end, which carries the time
   left as well, is the wide cell. */
.svc-usage__facts > .svc-fact {
  flex-basis: 6.5rem;
  padding-inline: 0.6rem;
}

.svc-usage__facts > .svc-fact--wide {
  flex: 2 1 11rem;
}

.svc-usage__facts > .svc-fact dd {
  font-size: 0.82rem;
}

.svc-usage__note {
  display: block;
  color: var(--ink-soft);
  font-size: 0.74rem;
  font-weight: 400;
  margin-block-start: 0.1rem;
}

/* An unlimited package: a mark, a short label and a sentence - never a metric, a ring or a bar,
   and no box drawn around so little. The cycle facts below it carry what is useful. */
.svc-usage-unlimited {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding-block: 0.15rem;
  min-inline-size: 0;
}

.svc-usage-unlimited__mark {
  display: grid;
  place-items: center;
  inline-size: 2.3rem;
  block-size: 2.3rem;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  color: var(--services-accent-text);
}

.svc-usage-unlimited__mark svg {
  inline-size: 1.3rem;
  block-size: 1.3rem;
}

.svc-usage-unlimited__note {
  margin: 0.25rem 0 0;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

/* -- addresses, DNS servers and the IP panel -------------------------------- */

/*
 * A list rather than a table. There are rarely more than a handful, each row is a value plus a
 * state plus one control, and a list stacks on a phone without either a horizontal scroller or a
 * table that has to be re-explained to a screen reader at every breakpoint. The panel is the
 * card; its entries are rows between hairlines, never cards of their own.
 */
.svc-addresses {
  display: grid;
  list-style: none;
  margin: 0;
  padding: 0;
  border-block-end: 1px solid var(--line);
}

.svc-address {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.6rem;
  min-block-size: 2.35rem;
  padding: 0.2rem 0.1rem;
  border-block-start: 1px solid var(--line);
}

/* CORE-FB-4 - a DNS server row reads "DNS 1 | address | Copy": its name, the address, and the
   copy control at the reading end. */
.svc-resolver {
  display: grid;
  grid-template-columns: minmax(3.5rem, auto) minmax(0, 1fr) auto;
}

.svc-resolver__name {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink-soft);
}

.svc-address__value {
  flex: 1 1 auto;
  min-inline-size: 0;
  font-weight: 700;
  /* An address is a Latin-script technical token. Isolating it keeps its dots
     and digits in the order they were written inside an otherwise RTL line. */
  direction: ltr;
  unicode-bidi: isolate;
  text-align: start;
  overflow-wrap: anywhere;
}

.svc-address__action {
  margin-inline-start: auto;
}

.svc-address__action .btn,
.svc-address > .btn {
  padding-block: 0.15rem;
}

/* "1 of 2 IPs": a quiet pill at the reading end of the heading, shown only when both the
   capacity and the IP list are current. */
.svc-ips__count {
  margin-inline-start: auto;
  padding: 0.12rem 0.55rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--ink-soft);
}

.svc-ips {
  display: grid;
  gap: 0.55rem;
  min-inline-size: 0;
}

.svc-ips > .notice {
  margin: 0;
}

/* A change in flight, said in one quiet line under the IPs - only while there is one. */
.svc-ips__status {
  margin: 0;
  padding-inline-start: 0.55rem;
  border-inline-start: 2px solid var(--services-accent-text);
  color: var(--ink-soft);
  font-size: 0.79rem;
  line-height: 1.55;
}

/*
 * The New IP form, in its own compact panel: the label over the field, the field and its action
 * on one row, the advisory current-IP helper as a small chip under them. The input may shrink to
 * the panel and never past it, so a phone never scrolls sideways.
 */
.svc-ipform {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: 0.45rem 0.6rem;
  min-inline-size: 0;
}

.svc-ipform__field {
  margin: 0;
  min-inline-size: 0;
}

/* Why the field matters now - a service waiting for its customer's IP: one short line under the
   heading, quieter than the heading and the action. */
.svc-newip__lead {
  margin: -0.15rem 0 0.5rem;
  color: var(--ink-soft);
  font-size: 0.8rem;
  line-height: 1.55;
}

.svc-ipform input {
  inline-size: 100%;
  max-inline-size: 100%;
  min-inline-size: 0;
  box-sizing: border-box;
}

.svc-ipform__submit {
  white-space: nowrap;
}

.svc-ipform .svc-ipsuggest {
  grid-column: 1 / -1;
  justify-self: start;
}

/*
 * The current-IP suggestion. Deliberately quieter than everything around it: a small chip with a
 * dashed hairline on the sunken ground, small soft text and a quiet button, so it reads as a
 * helper beside the field rather than as a status, a fact about the service, or a second primary
 * action competing with the submit.
 */
.svc-ipsuggest {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.15rem 0.55rem;
  padding: 0.3rem 0.6rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  min-inline-size: 0;
  max-inline-size: 100%;
}

.svc-ipsuggest__label,
.svc-ipsuggest__note {
  margin: 0;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

.svc-ipsuggest__note {
  flex-basis: 100%;
}

.svc-ipsuggest__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45rem;
}

.svc-ipsuggest__row .btn {
  padding-block: 0.1rem;
}

/* A Latin-script technical token inside an otherwise RTL line: isolated, so its
   dots and digits stay in the order they were written. */
.svc-ipsuggest__value {
  font-weight: 700;
  color: var(--ink);
  direction: ltr;
  unicode-bidi: isolate;
  overflow-wrap: anywhere;
}

/* -- renewal -------------------------------------------------------------- */

/* Past renewals: rows between hairlines, like the IPs. */
.svc-renewals {
  display: grid;
  list-style: none;
  margin: 0 0 0.6rem;
  padding: 0;
  border-block-end: 1px solid var(--line);
}

.svc-renewal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.6rem;
  padding: 0.3rem 0.1rem;
  border-block-start: 1px solid var(--line);
}

.svc-renewal__ident {
  flex: 1 1 12rem;
  min-inline-size: 0;
}

.svc-renewal__offer {
  font-weight: 700;
  margin: 0;
  overflow-wrap: anywhere;
}

.svc-renewal__when {
  color: var(--ink-soft);
  font-size: 0.76rem;
  margin: 0.05rem 0 0;
}

.svc-renew {
  display: grid;
  gap: 0.6rem;
  /* Stretch, deliberately: the chooser takes the panel's width rather than shrink-wrapping
     to its widest option. */
  justify-items: stretch;
}

/*
 * One organised choice group: one column on a phone, two by two on a tablet or a narrow desktop,
 * and one row of equal cards once the page is wide enough for four (fewer offers simply share the
 * row). Responsive rules over one set of markup - nothing is duplicated per breakpoint. The cards
 * sit in their own grid inside the fieldset, so the legend above them never holds a track open.
 */
.svc-renew__choices {
  border: 0;
  margin: 0;
  padding: 0;
  min-inline-size: 0;
}

.svc-renew__legend {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-block-end: 0.35rem;
  padding: 0;
}

.svc-renew__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.5rem;
}

@media (min-width: 40rem) {
  .svc-renew__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 68rem) {
  .svc-renew__grid {
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  }
}

/*
 * A real radio inside a label, styled as a card of equal height within its row: the radio fixed
 * at the reading start, the plan's names beside it, the price settled at the foot. The control is
 * never hidden from assistive technology or from the keyboard - it is the thing being styled,
 * arrow keys still move between the options, and the focus ring is drawn on the card so it is
 * visible at card size.
 */
.svc-choice {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 0.5rem;
  block-size: 100%;
  box-sizing: border-box;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
  min-inline-size: 0;
}

.svc-choice__input {
  margin: 0.2rem 0 0;
  inline-size: 1.05rem;
  block-size: 1.05rem;
  accent-color: var(--accent);
}

.svc-choice__body {
  display: grid;
  grid-template-rows: auto auto 1fr;
  gap: 0.1rem;
  block-size: 100%;
  min-inline-size: 0;
}

.svc-choice__product {
  font-weight: 700;
  overflow-wrap: anywhere;
}

.svc-choice__offer {
  color: var(--ink-soft);
  font-size: 0.8rem;
  overflow-wrap: anywhere;
}

.svc-choice__price {
  align-self: end;
  margin-block-start: 0.4rem;
  padding-block-start: 0.35rem;
  border-block-start: 1px solid var(--line);
  font-weight: 800;
  color: var(--services-accent-text);
}

/* Selection is shown by a heavier edge and a tinted ground as well as colour, and the radio
   itself remains the authoritative indicator for anybody who cannot see either. */
.svc-choice:has(.svc-choice__input:checked) {
  border-color: var(--accent-edge);
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent-edge);
}

.svc-choice:has(.svc-choice__input:focus-visible) {
  outline: 3px solid var(--ring);
  outline-offset: 2px;
}

/* The one action, at the reading end under the group: the cards and their prices say the rest. */
.svc-renew__foot {
  display: flex;
  justify-content: flex-end;
}

/* -- original purchase and support ----------------------------------------- */

.svc-foot {
  display: grid;
  gap: 0.7rem;
  align-items: center;
  min-inline-size: 0;
}

@media (min-width: 52rem) {
  .svc-foot {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* The original purchase is history, so it is one quiet line after the last operational panel:
   no card, no tiles that could be read as the current package - a heading, the offer and its
   date on one line, the explanation under them in small type. */
.svc-history {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.1rem 0.75rem;
  padding: 0.1rem 0.15rem 0;
  min-inline-size: 0;
}

.svc-history__title {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0;
}

.svc-history__line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2rem 0.75rem;
  margin: 0;
  font-size: 0.86rem;
  overflow-wrap: anywhere;
}

.svc-history__since {
  color: var(--ink-soft);
  font-size: 0.8rem;
}

.svc-history__note {
  flex-basis: 100%;
  color: var(--ink-soft);
  font-size: 0.74rem;
  line-height: 1.55;
  margin: 0;
}

/* The support path as one secondary row: a small icon, a sentence, the way in - on the plain
   surface, lighter than the operational panels above it. */
.svc-help {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45rem 0.65rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.5rem 0.7rem;
  min-inline-size: 0;
  text-align: start;
}

.svc-help__icon {
  display: grid;
  place-items: center;
  inline-size: 1.7rem;
  block-size: 1.7rem;
  flex: 0 0 auto;
  border-radius: var(--radius);
  background: var(--surface-sunken);
  border: 1px solid var(--line-strong);
  color: var(--services-accent-text);
}

.svc-help__icon svg {
  inline-size: 1rem;
  block-size: 1rem;
}

.svc-help__text {
  flex: 1 1 12rem;
  min-inline-size: 0;
}

.svc-help__title {
  font-family: var(--font-display);
  font-size: 0.9rem;
  font-weight: 800;
  margin: 0;
}

.svc-help__body {
  color: var(--ink-soft);
  font-size: 0.78rem;
  line-height: 1.55;
  margin: 0.05rem 0 0;
}

/* -- narrow --------------------------------------------------------------- */

@media (max-width: 900px) {
  /* The mobile artwork is a tall crop with its subject high in the frame, so it
     is anchored near the top and the copy sits on the floor the veil builds.
     Swapping the file rather than cropping the wide one is what keeps a phone
     from downloading a 2172px picture to show 390px of it. */
  .svc-hero::before {
    background-image: var(--services-hero-art-mobile);
    background-position: var(--services-hero-position-mobile);
  }

  .svc-hero::after {
    background: var(--services-hero-veil-mobile);
  }

  .svc-hero__inner {
    min-block-size: clamp(15rem, 11rem + 18vw, 21rem);
  }

  .svc-hero--detail .svc-hero__inner {
    min-block-size: clamp(8rem, 7rem + 6vw, 10.5rem);
  }

  /* On a narrow band the creature steps back behind the copy: a closer crop on its head alone
     (the wider composition's other figures would crowd a phone), narrower and fainter. */
  .svc-hero--detail .svc-hero__beast {
    inline-size: 52%;
    opacity: 0.5;
    background-size: 210% auto;
    background-position: 30% 2%;
    -webkit-mask-image: linear-gradient(to right, black 25%, transparent 88%);
    mask-image: linear-gradient(to right, black 25%, transparent 88%);
  }

  .svc-grid::before {
    background-image: var(--services-scene-art-mobile);
  }

  .svc-panel--identity::before {
    background-image: var(--services-frame-art-mobile);
  }

}

@media (max-width: 640px) {
  /* One card to a row well before the grid's own minimum would force it: two
     10rem columns technically fit a 390px phone and neither is readable. */
  .svc-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  /* The scene bleeds to the page gutter rather than past it, so nothing can
     introduce a horizontal scrollbar on a narrow viewport. */
  .svc-grid::before,
  .svc-grid::after {
    inset: calc(var(--gap) * -0.5);
  }

  .svc-listhead {
    align-items: stretch;
  }

  .svc-listhead .btn {
    inline-size: 100%;
  }

  .svc-card__foot {
    align-items: stretch;
  }

  .svc-card__foot .btn {
    inline-size: 100%;
  }

  /* The status badge moves under the name rather than squeezing it: at this
     width a long product name and a long state label cannot share a line
     without one of them becoming a column of single characters. */
  .svc-card__head {
    flex-wrap: wrap;
  }

  .svc-panel__action {
    margin-inline-start: 0;
    inline-size: 100%;
  }

  /* The activation hint takes its own line under the name and state, read from the start. */
  .svc-identity__hint {
    flex-basis: 100%;
    text-align: start;
  }

  .svc-panel__action .btn {
    inline-size: 100%;
  }

  .svc-renew,
  .svc-renew .btn {
    inline-size: 100%;
  }

  /* One card to a row: the plan's names at the reading start and the price at the end of the
     same card, rather than a tall card with the price under a divider. */
  .svc-choice__body {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: auto auto;
    column-gap: 0.6rem;
  }

  .svc-choice__product,
  .svc-choice__offer {
    grid-column: 1;
  }

  .svc-choice__price {
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: center;
    margin: 0;
    padding: 0;
    border: 0;
  }

  /* The New IP field and its action stack, the action full width under the thumb. */
  .svc-ipform {
    grid-template-columns: minmax(0, 1fr);
  }

  .svc-ipform__submit {
    inline-size: 100%;
  }

  .svc-ips__count {
    margin-inline-start: 0;
  }

  .svc-ring {
    inline-size: 5rem;
    block-size: 5rem;
  }

  .svc-ring__figure {
    font-size: 1.05rem;
  }
}

@media (max-width: 480px) {
  .svc-panel,
  .svc-help {
    padding-inline: 0.8rem;
  }

  /* A single column of full-size facts. Two 13rem columns do not fit 320px, and
     the grid would otherwise overflow rather than reflow. */
  .svc-facts,
  .svc-axes {
    grid-template-columns: minmax(0, 1fr);
  }

  /* The compact strips are short values (a bandwidth, a date), so two still sit side by side
     on a phone; the wide fact (the package) takes its own row above them. */
  .svc-facts--strip > .svc-fact {
    flex-basis: 7.5rem;
  }

  .svc-facts--strip > .svc-fact--wide {
    flex-basis: 100%;
  }

  /* The ring stays beside its readings, a size smaller, rather than stacking above them. */
  .svc-usage-meter {
    gap: 0.75rem;
  }

  .svc-ring {
    inline-size: 4.5rem;
    block-size: 4.5rem;
  }

  .svc-ring__figure {
    font-size: 0.95rem;
  }
}

/* ------------------------------------------------------- UX-7A wallet ----- */
/*
 * The customer's wallet (WALLET-UX-02 composition): a compact lead, one row of four
 * figures, the two actions side by side, one activity card and a closed guide.
 * Layout, rhythm, depth and veil only - no hue, no file path, no brand name - so a
 * deployment that supplies no artwork still gets this page on plain panels.
 *
 * The same two axes the dashboard, the shop and the services pages use.
 * **Content** is placed logically (`inline-start`/`inline-end`, `margin-inline`),
 * so Persian reads it from the right and English from the left with one set of
 * rules. **Artwork regions** are placed physically, because a photograph does
 * not mirror when the language does.
 *
 * Nothing here decides a number. Every figure arrives from the wallet service;
 * the stylesheet only chooses how large, how lit and where. Glow is kept to a
 * hairline and a faint wash: the figures carry the page, not the light.
 */

/* -- the lead band ---------------------------------------------------------- */

/* Rendered through `shell_lead`, outside `<main class="page">`, so the band
   reaches both screen edges without the centred column fighting it. */
.wallet-hero {
  position: relative;
  isolation: isolate;
  background-color: var(--wallet-hero-ground);
  border-block-end: 1px solid var(--wallet-hero-edge);
  overflow: hidden;
}

/* Picture and veil as two pseudo-element layers: the artwork never enters the
   accessibility tree, and there is no <img> a screen reader has to be told to
   ignore. */
.wallet-hero::before,
.wallet-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.wallet-hero::before {
  background-image: var(--wallet-hero-art);
  background-size: cover;
  background-position: var(--wallet-hero-position);
  background-repeat: no-repeat;
  z-index: -2;
}

.wallet-hero::after {
  background: var(--wallet-hero-veil);
  z-index: -1;
}

/* A band, not a billboard: about half the old height, so the first figure is
   on screen without scrolling. Still a minimum rather than a fixed height, so
   a long title in either language grows the band instead of being clipped. */
.wallet-hero__inner {
  max-width: var(--shell-width);
  margin: 0 auto;
  padding: clamp(1rem, 0.7rem + 1.2vw, 1.6rem) 1rem;
  min-block-size: clamp(8.5rem, 6.5rem + 4.5vw, 10.5rem);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Centred over the quiet middle of the composition, between the figure at one
   edge and the globe at the other - which is where the approved wallet
   composition puts it in both languages. */
.wallet-hero__copy {
  inline-size: min(100%, 40rem);
  margin-inline: auto;
  text-align: center;
}

.wallet-hero__eyebrow {
  display: block;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--wallet-accent-text);
  margin-block-end: 0.35rem;
}

.wallet-hero__title {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.2rem);
  font-weight: 800;
  line-height: 1.2;
  margin: 0 0 0.4rem;
}

.wallet-hero__mark {
  display: grid;
  place-items: center;
  inline-size: 2.4rem;
  block-size: 2.4rem;
  border-radius: var(--radius);
  border: 1px solid color-mix(in srgb, var(--wallet-total) 50%, transparent);
  background: color-mix(in srgb, var(--wallet-total) 12%, transparent);
  color: var(--wallet-total-ink);
}

.wallet-hero__mark svg {
  inline-size: 1.3rem;
  block-size: 1.3rem;
}

/* -- the four figures ------------------------------------------------------- */

.wallet-summary {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.85rem;
  margin-block-end: 1.1rem;
}

/*
 * One figure. Each card carries its own accent through one custom property, so
 * the rail, the tile and the number agree without four copies of every rule.
 * The accent is decoration: the heading names the figure, and the number is
 * the service's answer whatever colour it is drawn in.
 */
.wallet-stat {
  --wallet-stat-accent: var(--wallet-total);
  --wallet-stat-ink: var(--wallet-total-ink);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.9rem 1rem 0.95rem;
  background: var(--surface-raised);
  background-image: var(--wallet-card-glow);
  border: 1px solid color-mix(in srgb, var(--wallet-stat-accent) 32%, var(--line));
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  min-inline-size: 0;
}

.wallet-stat--available {
  --wallet-stat-accent: var(--wallet-available);
  --wallet-stat-ink: var(--wallet-available-ink);
}

.wallet-stat--withdrawable {
  --wallet-stat-accent: var(--wallet-withdrawable);
  --wallet-stat-ink: var(--wallet-withdrawable-ink);
}

.wallet-stat--reserved {
  --wallet-stat-accent: var(--wallet-reserved);
  --wallet-stat-ink: var(--wallet-reserved-ink);
}

/* The technical edge: a hairline rail along the top that fades at both ends. */
.wallet-stat::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 2px;
  background: linear-gradient(90deg, transparent, var(--wallet-stat-accent), transparent);
  opacity: 0.8;
  pointer-events: none;
}

.wallet-stat__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
}

.wallet-stat__label {
  font-size: 0.86rem;
  font-weight: 700;
  line-height: 1.4;
  color: var(--ink-soft);
  margin: 0;
}

.wallet-stat__icon {
  display: grid;
  place-items: center;
  inline-size: 2.15rem;
  block-size: 2.15rem;
  flex: 0 0 auto;
  border-radius: var(--radius);
  border: 1px solid color-mix(in srgb, var(--wallet-stat-accent) 45%, transparent);
  background: color-mix(in srgb, var(--wallet-stat-accent) 12%, transparent);
  color: var(--wallet-stat-ink);
}

.wallet-stat__icon svg {
  inline-size: 1.15rem;
  block-size: 1.15rem;
}

.wallet-stat__figure {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem;
  margin: 0;
}

/* A Latin-script numeral inside an otherwise RTL line: isolated, so the digits
   and any sign stay in the order they were written. */
.wallet-stat__value {
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 1.05rem + 0.9vw, 1.75rem);
  font-weight: 800;
  line-height: 1.2;
  color: var(--wallet-stat-ink);
  direction: ltr;
  unicode-bidi: isolate;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

.wallet-stat__unit {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--ink-faint);
}

/* A card's second answer: quieter than its own figure, never a card of its own. */
.wallet-stat__extra {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.15rem 0.6rem;
  margin: 0.1rem 0 0;
  padding-block-start: 0.45rem;
  border-block-start: 1px dashed var(--line);
  font-size: 0.76rem;
  color: var(--ink-faint);
}

.wallet-stat__extra dt {
  font-weight: 600;
}

.wallet-stat__extra dd {
  margin: 0;
  color: var(--ink-soft);
}

.wallet-stat__extra-value {
  font-weight: 700;
  direction: ltr;
  unicode-bidi: isolate;
  font-variant-numeric: tabular-nums;
}

/* -- no wallet -------------------------------------------------------------- */

.wallet-empty {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  justify-items: center;
  gap: 0.4rem;
  padding: clamp(1.4rem, 1.1rem + 1.4vw, 2.1rem) 1.25rem;
  margin-block-end: 1.1rem;
  text-align: center;
  background: var(--surface-raised);
  background-image: var(--wallet-card-glow);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

.wallet-empty::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 2px;
  background: linear-gradient(90deg, transparent, var(--wallet-total), transparent);
  pointer-events: none;
}

.wallet-empty__icon {
  display: grid;
  place-items: center;
  inline-size: 2.8rem;
  block-size: 2.8rem;
  margin-block-end: 0.2rem;
  border-radius: var(--radius);
  border: 1px solid color-mix(in srgb, var(--wallet-total) 50%, transparent);
  background: color-mix(in srgb, var(--wallet-total) 12%, transparent);
  color: var(--wallet-total-ink);
}

.wallet-empty__icon svg {
  inline-size: 1.35rem;
  block-size: 1.35rem;
}

.wallet-empty__title {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 800;
  margin: 0;
}

.wallet-empty__body {
  font-size: 0.9rem;
  color: var(--ink-soft);
  line-height: 1.8;
  margin: 0;
  max-inline-size: 46ch;
}

/* -- the two actions -------------------------------------------------------- */

/* Top-up at the reading start, withdrawal beside it: equal columns, and each
   panel stretches to the row so the pair reads as one balanced band. */
.wallet-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.85rem;
  align-items: stretch;
  margin-block-end: 1.1rem;
}

.wallet-actions--single {
  grid-template-columns: minmax(0, 1fr);
}

.wallet-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--surface-raised);
  background-image: var(--wallet-card-glow);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 1rem 1.1rem 1.1rem;
  min-inline-size: 0;
}

.wallet-panel__head {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  margin-block-end: 0.85rem;
}

.wallet-panel__icon {
  display: grid;
  place-items: center;
  inline-size: 2.3rem;
  block-size: 2.3rem;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--wallet-total) 50%, transparent);
  background: color-mix(in srgb, var(--wallet-total) 10%, transparent);
  color: var(--wallet-accent-text);
}

.wallet-withdraw .wallet-panel__icon {
  border-color: color-mix(in srgb, var(--wallet-withdrawable) 50%, transparent);
  background: color-mix(in srgb, var(--wallet-withdrawable) 10%, transparent);
  color: var(--wallet-withdrawable-ink);
}

.wallet-panel__icon svg {
  inline-size: 1.15rem;
  block-size: 1.15rem;
}

.wallet-panel__heading {
  min-inline-size: 0;
}

.wallet-panel__title {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 800;
  line-height: 1.4;
  margin: 0;
}

.wallet-panel__lede {
  font-size: 0.8rem;
  line-height: 1.7;
  color: var(--ink-faint);
  margin: 0.15rem 0 0;
}

/* The form sits in a sunken well: one frame for the fields, so a panel reads as
   heading, then the thing to fill in, then the button. The well fills what is left
   of its panel and the button settles at its foot, so the two actions' buttons
   line up however long either panel's copy runs. */
.wallet-topup__form,
.wallet-withdraw__form {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 0.85rem;
  background: color-mix(in srgb, var(--surface-sunken) 70%, transparent);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.wallet-field {
  margin: 0;
}

.wallet-field label {
  font-size: 0.82rem;
}

.wallet-field input[type="text"] {
  min-block-size: 2.6rem;
}

/* Amounts are written in Latin digits and read as numbers in both languages. */
.wallet-field input[name="amount_toman"] {
  direction: ltr;
  text-align: end;
  font-variant-numeric: tabular-nums;
}

.wallet-field .helptext {
  font-size: 0.74rem;
}

.wallet-topup__form .btn,
.wallet-withdraw__form .btn {
  inline-size: 100%;
  min-block-size: 2.6rem;
  margin-block-start: auto;
}

/* Two rails as a segmented choice: the native radios stay real radios - required,
   nothing pre-selected - and the label around each is the whole target. */
.wallet-topup__rails {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  border: 0;
}

.wallet-topup__rails legend {
  grid-column: 1 / -1;
  padding: 0;
  margin-block-end: 0.35rem;
  font-size: 0.82rem;
  font-weight: 700;
}

.wallet-topup__rail {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: 0.5rem;
  row-gap: 0.15rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface-raised);
  cursor: pointer;
  font-weight: 600;
  font-size: 0.86rem;
}

.wallet-topup__rail:has(input:checked) {
  border-color: var(--wallet-total);
  background: color-mix(in srgb, var(--wallet-total) 10%, var(--surface-raised));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--wallet-total) 40%, transparent);
}

.wallet-topup__rail:has(input:focus-visible) {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.wallet-topup__rail input {
  margin: 0;
  accent-color: var(--wallet-total);
}

.wallet-topup__rail .helptext {
  grid-column: 1 / -1;
  font-weight: 400;
  font-size: 0.72rem;
  line-height: 1.6;
  color: var(--ink-faint);
}

.wallet-topup__method {
  font-size: 0.8rem;
  line-height: 1.7;
  color: var(--ink-soft);
  margin: 0;
}

.wallet-panel__unavailable {
  flex: 1 1 auto;
  display: grid;
  align-content: center;
  gap: 0.25rem;
  padding: 0.85rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  font-size: 0.86rem;
  color: var(--ink-soft);
}

.wallet-panel__unavailable p {
  margin: 0;
}

.wallet-panel__hint {
  font-size: 0.76rem;
  color: var(--ink-faint);
}

/* -- coupon commission (CC-PENDING-WALLET-01) -------------------------------- */

/*
 * Commission on the customer's own coupons. Its figures sit in their own panel, never among the
 * wallet cards: pending commission is not wallet value. A wrapping grid, so a phone shows one
 * figure per row and a desktop several, without a media query.
 */
.coupon-commission {
  margin-block: 1rem;
}

.coupon-commission__figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  gap: 0.75rem;
  margin: 0.75rem 0;
}

.coupon-commission__figures dt {
  font-size: 0.8rem;
  color: var(--ink-faint);
}

.coupon-commission__figures dd {
  margin: 0;
  font-weight: 600;
}

/*
 * The scrolling frame is the containing block of the table's visually hidden labels: otherwise
 * those absolutely positioned spans escape its clipping and widen a right-to-left page.
 */
.coupon-commission .wallet-history__scroll {
  position: relative;
}

.coupon-commission__subtitle {
  font-size: 0.95rem;
  margin-block: 0.75rem 0.25rem;
}

.coupon-earnings__reason {
  display: block;
  font-size: 0.76rem;
  color: var(--ink-faint);
}

.coupon-earnings__code {
  font-family: var(--font-mono, monospace);
}

/* -- activity --------------------------------------------------------------- */

/*
 * One card, three native disclosures. A segment's summary is its tab: icon, name,
 * count and a chevron. Sharing one `name`, the three behave as tabs where the
 * browser supports exclusive details, and as an accordion where it does not -
 * either way every row is reachable with no script.
 */
.wallet-activity {
  background: var(--surface-raised);
  background-image: var(--wallet-card-glow);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 0.35rem;
  margin-block-end: 1.1rem;
}

.wallet-activity__title {
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 800;
  margin: 0;
  padding: 0.7rem 0.8rem 0.55rem;
}

.wallet-segment + .wallet-segment {
  border-block-start: 1px solid var(--line);
}

.wallet-segment__summary,
.wallet-help__summary {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 0.8rem;
  border-radius: var(--radius);
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.wallet-segment__summary::-webkit-details-marker,
.wallet-help__summary::-webkit-details-marker,
.wallet-row__more-toggle::-webkit-details-marker {
  display: none;
}

.wallet-segment__summary:hover,
.wallet-help__summary:hover {
  background: color-mix(in srgb, var(--wallet-total) 5%, transparent);
}

.wallet-segment__summary:focus-visible,
.wallet-help__summary:focus-visible,
.wallet-row__more-toggle:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

.wallet-segment__icon,
.wallet-help__icon {
  display: grid;
  place-items: center;
  inline-size: 1.9rem;
  block-size: 1.9rem;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  color: var(--ink-soft);
}

.wallet-segment__icon svg,
.wallet-help__icon svg {
  inline-size: 1rem;
  block-size: 1rem;
}

.wallet-segment[open] > .wallet-segment__summary .wallet-segment__icon {
  border-color: color-mix(in srgb, var(--wallet-total) 55%, transparent);
  background: color-mix(in srgb, var(--wallet-total) 12%, transparent);
  color: var(--wallet-total-ink);
}

.wallet-segment__title,
.wallet-help__title {
  font-weight: 700;
  font-size: 0.92rem;
}

.wallet-segment[open] > .wallet-segment__summary .wallet-segment__title {
  color: var(--wallet-accent-text);
}

.wallet-segment__count {
  min-inline-size: 1.6rem;
  padding: 0.05rem 0.45rem;
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  font-size: 0.74rem;
  font-weight: 700;
  text-align: center;
  color: var(--ink-soft);
}

/* A drawn chevron - no glyph, no image - that turns as its disclosure opens: down
   while closed, up while open. Physical borders on purpose: up and down do not
   mirror with the language. */
.wallet-segment__chevron {
  inline-size: 0.5rem;
  block-size: 0.5rem;
  margin-inline-start: auto;
  border-right: 2px solid var(--ink-faint);
  border-bottom: 2px solid var(--ink-faint);
  transform: translateY(-0.12rem) rotate(45deg);
  transition: transform 0.15s ease;
}

details[open] > summary .wallet-segment__chevron {
  transform: translateY(0.12rem) rotate(225deg);
}

.wallet-segment__body {
  padding: 0 0.45rem 0.6rem;
}

.wallet-segment__empty {
  margin: 0;
  padding: 0.85rem 0.6rem;
  font-size: 0.86rem;
  color: var(--ink-faint);
  text-align: center;
}

.wallet-history__empty-title {
  margin: 0;
  font-weight: 700;
  color: var(--ink-soft);
}

/* -- reservations (CLC-06, R0 D16) -------------------------------------------- */

/* Each ACTIVE hold: what it is for and how much, then the owner's own next step. On a phone the
   step drops beneath the line instead of squeezing it. */
.wallet-reservations {
  margin-block-start: var(--gap);
}

.wallet-reservation {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.25rem 0.75rem;
  min-inline-size: 0;
}

.wallet-reservation__what {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2rem 0.5rem;
  margin: 0;
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

.wallet-reservation__item + .wallet-reservation__item::before {
  content: "· ";
  color: var(--ink-faint);
}

.wallet-reservation__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.4rem;
}

.wallet-reservation__actions .inline-form {
  margin: 0;
}

@media (max-width: 40rem) {
  .wallet-reservations .wallet-rows > li {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 0.45rem;
  }

  .wallet-reservation__actions {
    justify-content: flex-start;
  }
}

/* -- rows ------------------------------------------------------------------- */

/* A compact list in a frame, one row per request: what it was, how much, when, and
   where it stands - then its own small Details disclosure at the row's end. */
.wallet-rows {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.wallet-rows > li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 0.75rem;
  padding: 0.55rem 0.8rem;
}

.wallet-rows > li + li {
  border-block-start: 1px solid var(--line);
}

.wallet-rows > li:hover {
  background: color-mix(in srgb, var(--wallet-total) 4%, transparent);
}

.wallet-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1.2fr) minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.75rem;
  min-inline-size: 0;
}

.wallet-row__icon {
  display: grid;
  place-items: center;
  inline-size: 1.75rem;
  block-size: 1.75rem;
  border-radius: 50%;
  border: 1px solid currentColor;
}

.wallet-row__icon svg {
  inline-size: 0.9rem;
  block-size: 0.9rem;
}

.wallet-row__icon--in {
  color: var(--wallet-credit);
}

.wallet-row__icon--out {
  color: var(--wallet-withdrawable-ink);
}

.wallet-row__amount {
  display: inline-flex;
  align-items: baseline;
  gap: 0.3rem;
  font-weight: 800;
  white-space: nowrap;
}

.wallet-row__amount .numeric {
  direction: ltr;
  unicode-bidi: isolate;
  font-variant-numeric: tabular-nums;
}

.wallet-row__when {
  font-size: 0.8rem;
  color: var(--ink-faint);
  direction: ltr;
  unicode-bidi: isolate;
  text-align: start;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.wallet-row__badge .badge {
  white-space: nowrap;
  font-size: 0.74rem;
}

/* Details: a quiet pill at the row's end; opened, it spans the row beneath it. */
.wallet-row__more {
  min-inline-size: 0;
}

.wallet-row__more[open] {
  grid-column: 1 / -1;
  margin-block-start: 0.5rem;
}

.wallet-row__more-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.65rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--ink-soft);
  cursor: pointer;
  list-style: none;
}

.wallet-row__more-toggle:hover {
  border-color: var(--wallet-total);
  color: var(--ink);
}

.wallet-row__more-body {
  display: grid;
  gap: 0.55rem;
  margin-block-start: 0.5rem;
  padding: 0.75rem 0.85rem;
  background: color-mix(in srgb, var(--surface-sunken) 70%, transparent);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.wallet-topups__note {
  font-size: 0.8rem;
  line-height: 1.75;
  color: var(--ink-soft);
  margin: 0;
}

.wallet-topups__action {
  display: grid;
  gap: 0.5rem;
  justify-items: start;
}

.wallet-topups__action .btn {
  min-block-size: 2.2rem;
  padding-block: 0.35rem;
  font-size: 0.84rem;
}

.wallet-topups__receipt .form-field {
  margin: 0;
}

/* The frozen instruction as a compact two-column sheet: label at the start, value at the end. */
.wallet-topups__instruction {
  display: grid;
  margin: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
}

.wallet-topups__instruction div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.4rem 0.7rem;
  font-size: 0.82rem;
}

.wallet-topups__instruction div + div {
  border-block-start: 1px solid var(--line);
}

.wallet-topups__instruction dt {
  color: var(--ink-faint);
}

.wallet-topups__instruction dd {
  margin: 0;
  font-weight: 700;
  overflow-wrap: anywhere;
}

/* -- history ---------------------------------------------------------------- */

/* The table scrolls inside its own frame if a very narrow screen needs it, so
   the page itself never scrolls sideways. */
.wallet-history__scroll {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.wallet-history__table {
  inline-size: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 0.86rem;
}

.wallet-history__table th {
  padding: 0.55rem 0.8rem;
  font-size: 0.76rem;
  font-weight: 700;
  text-align: start;
  color: var(--ink-faint);
  background: var(--surface-sunken);
  border-block-end: 1px solid var(--line-strong);
  white-space: nowrap;
}

.wallet-history__table td {
  padding: 0.5rem 0.8rem;
  border-block-end: 1px solid var(--line);
  vertical-align: middle;
}

.wallet-history__table tbody tr:last-child td {
  border-block-end: 0;
}

.wallet-history__table tbody tr:hover td {
  background: color-mix(in srgb, var(--wallet-total) 4%, transparent);
}

/* Date and time on one line: the time is the quieter half. */
.wallet-history__when time {
  display: inline-flex;
  align-items: baseline;
  gap: 0.5rem;
}

.wallet-history__date,
.wallet-history__time {
  direction: ltr;
  unicode-bidi: isolate;
  text-align: start;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.wallet-history__date {
  font-weight: 700;
}

.wallet-history__time {
  font-size: 0.76rem;
  color: var(--ink-faint);
}

.wallet-history__reason {
  color: var(--ink-soft);
}

.wallet-history__table .wallet-history__amount-head,
.wallet-history__amount {
  text-align: end;
}

.wallet-amount {
  display: inline-flex;
  align-items: baseline;
  gap: 0.3rem;
  white-space: nowrap;
}

.wallet-amount__value {
  font-weight: 800;
  direction: ltr;
  unicode-bidi: isolate;
  font-variant-numeric: tabular-nums;
}

.wallet-amount--credit {
  color: var(--wallet-credit);
}

.wallet-amount--debit {
  color: var(--wallet-debit);
}

.wallet-amount__unit {
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--ink-faint);
}

/* -- the guide -------------------------------------------------------------- */

/* Closed by default, one line tall: it answers when asked and never competes with
   the figures or the actions. Open, the four meanings sit in a compact grid. */
.wallet-help {
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 0.35rem;
}

.wallet-help[open] > .wallet-help__summary .wallet-help__icon {
  border-color: color-mix(in srgb, var(--wallet-available) 55%, transparent);
  color: var(--wallet-available-ink);
}

.wallet-help__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.6rem;
  margin: 0;
  padding: 0.2rem 0.45rem 0.6rem;
}

.wallet-help__item {
  --wallet-help-accent: var(--wallet-total);
  padding: 0.7rem 0.8rem;
  border: 1px solid var(--line);
  border-inline-start: 2px solid var(--wallet-help-accent);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface-sunken) 60%, transparent);
}

.wallet-help__item--available {
  --wallet-help-accent: var(--wallet-available);
}

.wallet-help__item--withdrawable {
  --wallet-help-accent: var(--wallet-withdrawable);
}

.wallet-help__item--reserved {
  --wallet-help-accent: var(--wallet-reserved);
}

.wallet-help__item dt {
  font-weight: 700;
  font-size: 0.86rem;
  margin-block-end: 0.25rem;
}

.wallet-help__item dd {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.75;
  color: var(--ink-soft);
}

/* -- narrow ----------------------------------------------------------------- */

@media (max-width: 64rem) {
  .wallet-summary {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .wallet-help__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 52rem) {
  .wallet-actions {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Row on two lines: what and how much first, when and where it stands beneath. */
  .wallet-row {
    grid-template-columns: auto minmax(0, 1fr) auto;
    row-gap: 0.15rem;
  }

  .wallet-row__when {
    grid-column: 2;
    grid-row: 2;
  }

  .wallet-row__badge {
    grid-column: 3;
    grid-row: 1 / span 2;
  }
}

@media (max-width: 34rem) {
  .wallet-hero__inner {
    min-block-size: 7.5rem;
  }

  .wallet-summary {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.6rem;
  }

  .wallet-stat {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 0.75rem;
    row-gap: 0.2rem;
  }

  .wallet-stat__head {
    display: contents;
  }

  .wallet-stat__label {
    grid-column: 1;
    grid-row: 1;
  }

  .wallet-stat__icon {
    grid-column: 2;
    grid-row: 1 / span 2;
  }

  .wallet-stat__figure,
  .wallet-stat__extra {
    grid-column: 1 / -1;
  }

  .wallet-stat__figure {
    grid-column: 1;
  }

  .wallet-topup__rails,
  .wallet-help__grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .wallet-rows > li {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 0.4rem;
  }

  .wallet-row__more {
    justify-self: end;
  }

  .wallet-row__more[open] {
    justify-self: stretch;
    margin-block-start: 0;
  }

  .wallet-history__table td,
  .wallet-history__table th {
    padding-inline: 0.6rem;
  }

  .wallet-history__when time {
    display: grid;
    gap: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .wallet-segment__chevron {
    transition: none;
  }
}

/* ------------------------------------------------------- UX-7B orders ----- */
/*
 * The customer's orders: one row per order, its commercial state in words, and
 * two destinations - the recorded details and the payment status. Layout,
 * rhythm, depth and veil only - no hue, no file path, no brand name.
 *
 * The same two axes as the wallet: content placed logically, artwork placed
 * physically. State is never colour alone - every badge carries the domain's own
 * translated word.
 */

/* -- the lead band ---------------------------------------------------------- */

.orders-hero {
  position: relative;
  isolation: isolate;
  background-color: var(--orders-hero-ground);
  border-block-end: 1px solid var(--orders-hero-edge);
  overflow: hidden;
}

.orders-hero::before,
.orders-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.orders-hero::before {
  background-image: var(--orders-hero-art);
  background-size: cover;
  background-position: var(--orders-hero-position);
  background-repeat: no-repeat;
  z-index: -2;
}

.orders-hero::after {
  background: var(--orders-hero-veil);
  z-index: -1;
}

.orders-hero__inner {
  max-width: var(--shell-width);
  margin: 0 auto;
  padding: clamp(1.75rem, 1rem + 2.4vw, 3rem) 1rem;
  min-block-size: clamp(15rem, 11rem + 9vw, 20rem);
  display: flex;
  align-items: center;
  justify-content: center;
}

.orders-hero__copy {
  inline-size: min(100%, 44rem);
  margin-inline: auto;
  text-align: center;
}

.orders-hero__eyebrow {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--orders-accent-text);
  margin-block-end: 0.55rem;
}

.orders-hero__title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.35rem + 2.4vw, 3.1rem);
  font-weight: 800;
  line-height: 1.2;
  margin: 0 0 0.75rem;
}

.orders-hero__lede {
  color: var(--ink-soft);
  line-height: 1.9;
  margin: 0 auto;
  max-inline-size: 46ch;
}

/* -- the two panels --------------------------------------------------------- */

/* One column at every width. Six facts and two destinations per row need the
   whole content width; a side panel beside them pushed the actions column out of
   its frame on a desktop. What the three answers mean reads as a closing band. */
.orders-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    "history"
    "info";
  gap: var(--gap);
  align-items: start;
}

.orders-panel {
  position: relative;
  background: var(--surface-raised);
  background-image: var(--orders-card-glow);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 1.3rem 1.35rem 1.4rem;
  min-inline-size: 0;
}

.orders-history {
  grid-area: history;
}

.orders-info {
  grid-area: info;
}

.orders-panel__head {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin-block-end: 1.15rem;
}

.orders-panel__icon {
  display: grid;
  place-items: center;
  inline-size: 2.9rem;
  block-size: 2.9rem;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--orders-accent) 50%, transparent);
  background: color-mix(in srgb, var(--orders-accent) 10%, transparent);
  color: var(--orders-accent-text);
}

.orders-panel__icon svg {
  inline-size: 1.35rem;
  block-size: 1.35rem;
}

.orders-panel__heading {
  min-inline-size: 0;
}

.orders-panel__title {
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 800;
  line-height: 1.35;
  margin: 0;
}

.orders-panel__lede {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin: 0.15rem 0 0;
}

/* -- the table -------------------------------------------------------------- */

/* Scrolls inside its own frame if a mid-width screen needs it, so the page
   itself never scrolls sideways. */
.orders-table__frame {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.orders-table {
  inline-size: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
}

.orders-table th {
  text-align: start;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--ink-soft);
  background: var(--surface-sunken);
  padding: 0.75rem 0.9rem;
  border-block-end: 1px solid var(--line);
  white-space: nowrap;
}

.orders-table td {
  padding: 0.9rem;
  border-block-end: 1px solid var(--line);
  vertical-align: middle;
}

.orders-table tbody tr:last-child td {
  border-block-end: 0;
}

.orders-table tbody tr:hover td {
  background: color-mix(in srgb, var(--orders-accent) 4%, transparent);
}

/* A public id is long and has no spaces. It is shown whole - it is what support
   will ask for - in a quieter monospace that may break anywhere, and always left
   to right, because a UUID does not mirror. */
.orders-table__id {
  display: block;
  max-inline-size: 19ch;
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 0.76rem;
  line-height: 1.55;
  color: var(--ink-soft);
  overflow-wrap: anywhere;
  unicode-bidi: isolate;
  /* UX7-FINAL-01. The id also carries the shared `.numeric` class, which keeps
     figures on one line. For a 36-character reference that meant it never
     wrapped: it ran past its column on a desktop and past the card on a phone -
     off the right edge in English, which scrolled the page sideways, and off the
     left edge in Persian. Allowing wrapping lets it break at its hyphens inside
     its own box, still whole and still left to right. */
  white-space: normal;
}

.orders-table__when time {
  display: grid;
  gap: 0.1rem;
}

.orders-table__date {
  font-weight: 700;
}

.orders-table__time {
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.orders-table__items,
.orders-table__items-head {
  text-align: center;
}

.orders-table__total,
.orders-table__total-head {
  text-align: end;
  white-space: nowrap;
}

.orders-table__total strong {
  font-size: 1rem;
  font-weight: 800;
}

.orders-table__unit {
  font-size: 0.78rem;
  color: var(--ink-soft);
  margin-inline-start: 0.25rem;
}

.orders-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  justify-content: flex-end;
}

.orders-actions .btn {
  white-space: nowrap;
}

/* -- no orders -------------------------------------------------------------- */

.orders-empty {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 0.35rem;
  padding: 2.25rem 1rem 2rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
}

.orders-empty p {
  margin: 0;
}

.orders-empty__icon {
  display: grid;
  place-items: center;
  inline-size: 3.25rem;
  block-size: 3.25rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--orders-accent) 10%, transparent);
  color: var(--orders-accent-text);
  margin-block-end: 0.35rem;
}

.orders-empty__icon svg {
  inline-size: 1.5rem;
  block-size: 1.5rem;
}

.orders-empty__title {
  font-weight: 800;
}

.orders-empty__note {
  font-size: 0.88rem;
  color: var(--ink-soft);
  margin-block-end: 0.75rem !important;
}

/* -- what the three answers are --------------------------------------------- */

.orders-info__list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.65rem;
  margin: 0;
}

.orders-info__item {
  padding: 0.85rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface-sunken) 70%, transparent);
}

.orders-info__term {
  font-weight: 800;
  margin: 0 0 0.25rem;
}

.orders-info__desc {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.85;
  color: var(--ink-soft);
}

.orders-info__more {
  margin: 0.95rem 0 0;
  font-size: 0.88rem;
  font-weight: 700;
}

.orders-info__more a {
  color: var(--orders-accent-text);
}

/* -- narrow ----------------------------------------------------------------- */

@media (max-width: 900px) {
  .orders-hero::before {
    background-image: var(--orders-hero-art-mobile);
    background-position: 50% 8%;
  }

  .orders-hero::after {
    background: var(--orders-hero-veil-mobile);
  }

  .orders-hero__inner {
    min-block-size: clamp(20rem, 15rem + 22vw, 26rem);
    align-items: flex-end;
    padding-block: 1.25rem 1.75rem;
  }

  .orders-info__list {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* A six-column row does not fit a phone, so each order becomes a card of
   labelled facts. The table keeps its roles in the markup; the visible label is
   given an empty alternative so a screen reader hears the column header once,
   not twice. */
@media (max-width: 720px) {
  .orders-panel {
    padding: 1.1rem 0.95rem 1.2rem;
  }

  .orders-table__frame {
    overflow: visible;
    border: 0;
  }

  .orders-table,
  .orders-table tbody,
  .orders-table tr,
  .orders-table td {
    display: block;
  }

  .orders-table thead {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .orders-table tbody tr {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface-raised);
    padding: 0.2rem 0.9rem;
    margin-block-end: 0.7rem;
  }

  .orders-table tbody tr:last-child {
    margin-block-end: 0;
  }

  .orders-table td,
  .orders-table tbody tr:last-child td {
    display: grid;
    grid-template-columns: minmax(6.5rem, max-content) minmax(0, 1fr);
    align-items: baseline;
    gap: 0.75rem;
    padding: 0.6rem 0;
    border-block-end: 1px solid var(--line);
    text-align: start;
  }

  .orders-table td::before {
    content: attr(data-label);
    content: attr(data-label) / "";
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--ink-soft);
  }

  .orders-table tbody tr:hover td {
    background: none;
  }

  .orders-table td.orders-table__actions {
    grid-template-columns: minmax(0, 1fr);
    border-block-end: 0;
  }

  .orders-table td.orders-table__actions::before {
    content: none;
  }

  .orders-table__id {
    max-inline-size: none;
  }

  .orders-table__when time {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
  }

  .orders-actions {
    justify-content: stretch;
  }

  .orders-actions .btn {
    flex: 1 1 10rem;
    justify-content: center;
  }
}

/* ------------------------------------------------ UX-7C notifications ----- */
/*
 * The customer's inbox and one notification. Layout, rhythm, depth and veil
 * only - no hue, no file path, no brand name.
 *
 * Unread is told three ways at once: a word in a badge, a heavier title and an
 * accented edge. The word is the one that carries the meaning; the other two are
 * for scanning. Nothing here describes a delivery channel, because the page has
 * none to describe.
 */

/* -- the lead band ---------------------------------------------------------- */

.inbox-hero {
  position: relative;
  isolation: isolate;
  background-color: var(--inbox-hero-ground);
  border-block-end: 1px solid var(--inbox-hero-edge);
  overflow: hidden;
}

.inbox-hero::before,
.inbox-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.inbox-hero::before {
  background-image: var(--inbox-hero-art);
  background-size: cover;
  background-position: var(--inbox-hero-position);
  background-repeat: no-repeat;
  z-index: -2;
}

.inbox-hero::after {
  background: var(--inbox-hero-veil);
  z-index: -1;
}

.inbox-hero__inner {
  max-width: var(--shell-width);
  margin: 0 auto;
  padding: clamp(1.75rem, 1rem + 2.4vw, 3rem) 1rem;
  min-block-size: clamp(15rem, 11rem + 9vw, 20rem);
  display: flex;
  align-items: center;
  justify-content: center;
}

.inbox-hero__copy {
  inline-size: min(100%, 44rem);
  margin-inline: auto;
  text-align: center;
}

.inbox-hero__eyebrow {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--inbox-accent-text);
  margin-block-end: 0.55rem;
}

.inbox-hero__title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.35rem + 2.4vw, 3.1rem);
  font-weight: 800;
  line-height: 1.2;
  margin: 0 0 0.75rem;
}

.inbox-hero__lede {
  color: var(--ink-soft);
  line-height: 1.9;
  margin: 0 auto;
  max-inline-size: 46ch;
}

/* -- panels ----------------------------------------------------------------- */

.inbox-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--gap);
}

.inbox-panel {
  position: relative;
  background: var(--surface-raised);
  background-image: var(--inbox-card-glow);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 1.3rem 1.35rem 1.4rem;
  min-inline-size: 0;
}

.inbox-panel__head {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin-block-end: 1.15rem;
}

.inbox-panel__icon {
  display: grid;
  place-items: center;
  inline-size: 2.9rem;
  block-size: 2.9rem;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--inbox-accent) 50%, transparent);
  background: color-mix(in srgb, var(--inbox-accent) 10%, transparent);
  color: var(--inbox-accent-text);
}

.inbox-panel__icon svg {
  inline-size: 1.35rem;
  block-size: 1.35rem;
}

.inbox-panel__heading {
  min-inline-size: 0;
}

.inbox-panel__title {
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 800;
  line-height: 1.35;
  margin: 0;
}

.inbox-panel__lede {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin: 0.15rem 0 0;
}

/* -- the list --------------------------------------------------------------- */

.inbox-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}

.inbox-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.9rem;
  padding: 0.95rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-raised);
}

.inbox-item--unread {
  border-inline-start: 3px solid var(--inbox-accent);
  background: color-mix(in srgb, var(--inbox-accent) 5%, var(--surface-raised));
}

.inbox-item__icon {
  --inbox-tone: var(--inbox-accent);
  display: grid;
  place-items: center;
  inline-size: 2.75rem;
  block-size: 2.75rem;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--inbox-tone) 55%, transparent);
  background: color-mix(in srgb, var(--inbox-tone) 12%, transparent);
  color: var(--inbox-tone);
}

.inbox-item__icon--payments {
  --inbox-tone: var(--inbox-tone-payments);
}

.inbox-item__icon--support {
  --inbox-tone: var(--inbox-tone-support);
}

.inbox-item__icon--dns {
  --inbox-tone: var(--inbox-tone-dns);
}

.inbox-item__icon svg {
  inline-size: 1.3rem;
  block-size: 1.3rem;
}

.inbox-item__body {
  min-inline-size: 0;
}

.inbox-item__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 0.6rem;
  margin: 0 0 0.3rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.inbox-item__source {
  font-weight: 700;
}

.inbox-item__title {
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.6;
  margin: 0 0 0.2rem;
}

.inbox-item--unread .inbox-item__title {
  font-weight: 800;
}

.inbox-item__title a {
  color: var(--ink);
  text-decoration: none;
}

.inbox-item__title a:hover {
  text-decoration: underline;
}

.inbox-item__excerpt {
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.85;
  color: var(--ink-soft);
  overflow-wrap: anywhere;
}

.inbox-item__action form {
  margin: 0;
}

/* -- nothing yet ------------------------------------------------------------ */

.inbox-empty {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 0.35rem;
  padding: 2.25rem 1rem 2rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
}

.inbox-empty p {
  margin: 0;
}

.inbox-empty__icon {
  display: grid;
  place-items: center;
  inline-size: 3.25rem;
  block-size: 3.25rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--inbox-accent) 10%, transparent);
  color: var(--inbox-accent-text);
  margin-block-end: 0.35rem;
}

.inbox-empty__icon svg {
  inline-size: 1.5rem;
  block-size: 1.5rem;
}

.inbox-empty__title {
  font-weight: 800;
}

.inbox-empty__note {
  font-size: 0.88rem;
  color: var(--ink-soft);
}

/* -- about ------------------------------------------------------------------ */

.inbox-info .inbox-panel__head {
  margin-block-end: 0.85rem;
}

.inbox-info__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.65rem;
}

.inbox-info__list li {
  padding: 0.85rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface-sunken) 70%, transparent);
  font-size: 0.88rem;
  line-height: 1.85;
  color: var(--ink-soft);
}

/* -- one notification ------------------------------------------------------- */

/* One reading column, centred, with its way back aligned to it. */
.inbox-back,
.inbox-detail {
  max-inline-size: 48rem;
  margin-inline: auto;
}

.inbox-back {
  margin-block: 0 0.85rem;
  font-size: 0.9rem;
  font-weight: 700;
}

.inbox-back a {
  color: var(--inbox-accent-text);
}

.inbox-detail--unread {
  border-inline-start: 3px solid var(--inbox-accent);
}

.inbox-detail__head {
  display: flex;
  align-items: flex-start;
  gap: 0.95rem;
  margin-block-end: 1rem;
}

.inbox-detail__heading {
  min-inline-size: 0;
}

.inbox-detail__title {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 1.15rem + 1vw, 1.85rem);
  font-weight: 800;
  line-height: 1.4;
  margin: 0;
  overflow-wrap: anywhere;
}

.inbox-detail__body {
  margin: 0 0 1.25rem;
  line-height: 2;
  overflow-wrap: anywhere;
}

.inbox-detail__foot {
  padding-block-start: 1rem;
  border-block-start: 1px solid var(--line);
}

.inbox-detail__foot form {
  margin: 0;
}

.inbox-detail__read {
  margin: 0;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

/* -- narrow ----------------------------------------------------------------- */

@media (max-width: 900px) {
  .inbox-hero::before {
    background-image: var(--inbox-hero-art-mobile);
    background-position: 50% 8%;
  }

  .inbox-hero::after {
    background: var(--inbox-hero-veil-mobile);
  }

  .inbox-hero__inner {
    min-block-size: clamp(20rem, 15rem + 22vw, 26rem);
    align-items: flex-end;
    padding-block: 1.25rem 1.75rem;
  }

  .inbox-info__list {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 640px) {
  .inbox-panel {
    padding: 1.1rem 0.95rem 1.2rem;
  }

  .inbox-item {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
    gap: 0.75rem;
    padding: 0.85rem 0.85rem 0.9rem;
  }

  .inbox-item__icon {
    inline-size: 2.4rem;
    block-size: 2.4rem;
  }

  .inbox-item__action {
    grid-column: 1 / -1;
  }

  .inbox-item__action .btn {
    inline-size: 100%;
    justify-content: center;
  }
}

/* ------------------------------------------------------ UX-7D support ----- */
/*
 * The customer's tickets, the open-a-ticket form, and one ticket's conversation.
 * Layout, rhythm, depth and veil only - no hue, no file path, no brand name.
 *
 * In a conversation the customer's own messages sit at the inline end and
 * support's at the inline start, so Persian and English both read "them, then
 * me" in their own direction. Side and tint are for scanning; every message also
 * names who spoke.
 */

/* -- the lead band ---------------------------------------------------------- */

.support-hero {
  position: relative;
  isolation: isolate;
  background-color: var(--support-hero-ground);
  border-block-end: 1px solid var(--support-hero-edge);
  overflow: hidden;
}

.support-hero::before,
.support-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.support-hero::before {
  background-image: var(--support-hero-art);
  background-size: cover;
  background-position: var(--support-hero-position);
  background-repeat: no-repeat;
  z-index: -2;
}

.support-hero::after {
  background: var(--support-hero-veil);
  z-index: -1;
}

.support-hero__inner {
  max-width: var(--shell-width);
  margin: 0 auto;
  padding: clamp(1.75rem, 1rem + 2.4vw, 3rem) 1rem;
  min-block-size: clamp(15rem, 11rem + 9vw, 20rem);
  display: flex;
  align-items: center;
  justify-content: center;
}

.support-hero__copy {
  inline-size: min(100%, 44rem);
  margin-inline: auto;
  text-align: center;
}

.support-hero__eyebrow {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--support-accent-text);
  margin-block-end: 0.55rem;
}

.support-hero__title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.35rem + 2.4vw, 3.1rem);
  font-weight: 800;
  line-height: 1.2;
  margin: 0 0 0.75rem;
}

.support-hero__lede {
  color: var(--ink-soft);
  line-height: 1.9;
  margin: 0 auto;
  max-inline-size: 46ch;
}

/* -- panels ----------------------------------------------------------------- */

.support-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  grid-template-areas:
    "tickets open"
    "info info";
  gap: var(--gap);
  align-items: start;
}

.support-tickets {
  grid-area: tickets;
}

.support-open {
  grid-area: open;
  scroll-margin-block-start: 1rem;
}

.support-info {
  grid-area: info;
}

.support-panel {
  position: relative;
  background: var(--surface-raised);
  background-image: var(--support-card-glow);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 1.3rem 1.35rem 1.4rem;
  min-inline-size: 0;
}

.support-panel__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.85rem;
  margin-block-end: 1.15rem;
}

.support-panel__icon {
  display: grid;
  place-items: center;
  inline-size: 2.9rem;
  block-size: 2.9rem;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--support-accent) 50%, transparent);
  background: color-mix(in srgb, var(--support-accent) 10%, transparent);
  color: var(--support-accent-text);
}

.support-panel__icon svg {
  inline-size: 1.35rem;
  block-size: 1.35rem;
}

.support-panel__heading {
  flex: 1 1 12rem;
  min-inline-size: 0;
}

.support-panel__title {
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 800;
  line-height: 1.35;
  margin: 0;
}

.support-panel__lede {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin: 0.15rem 0 0;
}

.support-panel__action {
  flex: 0 0 auto;
}

/* -- the ticket list -------------------------------------------------------- */

.support-ticket-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}

.support-ticket {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.9rem;
  padding: 0.9rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-raised);
}

.support-ticket__main {
  min-inline-size: 0;
}

.support-ticket__subject {
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.6;
  margin: 0 0 0.2rem;
  overflow-wrap: anywhere;
}

.support-ticket__subject a {
  color: var(--ink);
  text-decoration: none;
}

.support-ticket__subject a:hover {
  text-decoration: underline;
}

.support-ticket__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 0.75rem;
  margin: 0;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.support-ticket__status {
  flex: 0 0 auto;
}

.support-empty {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 0.35rem;
  padding: 2rem 1rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
}

.support-empty p {
  margin: 0;
}

.support-empty__icon {
  display: grid;
  place-items: center;
  inline-size: 3.25rem;
  block-size: 3.25rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--support-accent) 10%, transparent);
  color: var(--support-accent-text);
  margin-block-end: 0.35rem;
}

.support-empty__icon svg {
  inline-size: 1.5rem;
  block-size: 1.5rem;
}

.support-empty__title {
  font-weight: 800;
}

/* -- forms ------------------------------------------------------------------ */

.support-form textarea {
  min-block-size: 7rem;
}

.support-form .form-actions {
  margin-block-start: 0.25rem;
}

/* -- about ------------------------------------------------------------------ */

.support-info .support-panel__head {
  margin-block-end: 0.85rem;
}

.support-info__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.65rem;
}

.support-info__list li {
  padding: 0.85rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface-sunken) 70%, transparent);
  font-size: 0.88rem;
  line-height: 1.85;
  color: var(--ink-soft);
}

/* -- one ticket ------------------------------------------------------------- */

.support-detail {
  display: grid;
  gap: var(--gap);
  max-inline-size: 52rem;
  margin-inline: auto;
}

.support-back {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 700;
}

.support-back a {
  color: var(--support-accent-text);
}

.support-ticket-head {
  display: flex;
  align-items: flex-start;
  gap: 0.95rem;
}

.support-ticket-head__main {
  min-inline-size: 0;
}

.support-ticket-head .support-ticket__meta {
  margin-block-end: 0.4rem;
}

.support-ticket-head__title {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 1.15rem + 1vw, 1.85rem);
  font-weight: 800;
  line-height: 1.4;
  margin: 0;
  overflow-wrap: anywhere;
}

.support-conversation .support-panel__title {
  margin-block-end: 1rem;
}

.support-thread {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.9rem;
}

.support-message {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  max-inline-size: min(100%, 40rem);
}

.support-message--customer {
  flex-direction: row-reverse;
  margin-inline-start: auto;
}

.support-message__avatar {
  display: grid;
  place-items: center;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: var(--surface-sunken);
  color: var(--ink-soft);
}

.support-message--staff .support-message__avatar {
  border-color: color-mix(in srgb, var(--support-staff) 55%, transparent);
  background: color-mix(in srgb, var(--support-staff) 12%, transparent);
  color: var(--support-staff);
}

.support-message--customer .support-message__avatar {
  border-color: color-mix(in srgb, var(--support-accent) 55%, transparent);
  background: color-mix(in srgb, var(--support-accent) 12%, transparent);
  color: var(--support-accent-text);
}

.support-message__avatar svg {
  inline-size: 1.2rem;
  block-size: 1.2rem;
}

.support-message__bubble {
  min-inline-size: 0;
  padding: 0.8rem 0.95rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-sunken);
}

.support-message--staff .support-message__bubble {
  border-inline-start: 3px solid color-mix(in srgb, var(--support-staff) 70%, transparent);
}

.support-message--customer .support-message__bubble {
  background: color-mix(in srgb, var(--support-accent) 7%, var(--surface-raised));
}

.support-message__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.65rem;
  margin: 0 0 0.35rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.support-message__meta strong {
  color: var(--ink);
  font-size: 0.88rem;
}

.support-message__body {
  margin: 0;
  line-height: 1.95;
  overflow-wrap: anywhere;
}

.support-attachments {
  list-style: none;
  margin: 0.7rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}

.support-attachment {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  max-inline-size: 100%;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface-raised);
  color: var(--ink);
  font-size: 0.82rem;
  text-decoration: none;
}

.support-attachment:hover {
  border-color: var(--support-accent);
}

.support-attachment__icon svg {
  inline-size: 1rem;
  block-size: 1rem;
  display: block;
}

.support-attachment__name {
  overflow-wrap: anywhere;
  font-weight: 600;
}

.support-attachment__size {
  color: var(--ink-soft);
  white-space: nowrap;
}

.support-closed {
  margin: 0;
}

/* -- narrow ----------------------------------------------------------------- */

@media (max-width: 900px) {
  .support-hero::before {
    background-image: var(--support-hero-art-mobile);
    background-position: 50% 8%;
  }

  .support-hero::after {
    background: var(--support-hero-veil-mobile);
  }

  .support-hero__inner {
    min-block-size: clamp(20rem, 15rem + 22vw, 26rem);
    align-items: flex-end;
    padding-block: 1.25rem 1.75rem;
  }

  .support-layout {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "tickets"
      "open"
      "info";
  }

  .support-info__list {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 640px) {
  .support-panel {
    padding: 1.1rem 0.95rem 1.2rem;
  }

  .support-panel__action {
    inline-size: 100%;
    justify-content: center;
  }

  .support-ticket {
    flex-direction: column;
    align-items: stretch;
  }

  .support-message {
    max-inline-size: 100%;
  }

  .support-message__avatar {
    inline-size: 2.1rem;
    block-size: 2.1rem;
  }
}

/* ------------------------------------------------ UX-8A content indexes --- */
/*
 * The article and tutorial indexes: a lead band, then a grid of editorial cards.
 * Layout, rhythm, depth and veil only - no hue, no file path, no brand name.
 *
 * Calmer than the account pages on purpose: a card answers a pointer or the
 * keyboard by firming its border and shadow, and does not move. Content is
 * placed logically, so Persian reads the grid from the right and English from
 * the left with one set of rules; the band's artwork is placed physically,
 * because a picture does not mirror.
 */

/* -- the lead band ---------------------------------------------------------- */

.content-hero {
  position: relative;
  isolation: isolate;
  background-color: var(--content-hero-ground);
  border-block-end: 1px solid var(--content-hero-edge);
  overflow: hidden;
}

.content-hero::before,
.content-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.content-hero::before {
  background-image: var(--content-hero-art);
  background-size: cover;
  background-position: var(--content-hero-position);
  background-repeat: no-repeat;
  z-index: -2;
}

.content-hero::after {
  background: var(--content-hero-veil);
  z-index: -1;
}

.content-hero__inner {
  max-width: var(--shell-width);
  margin: 0 auto;
  padding: clamp(1.75rem, 1rem + 2.4vw, 3rem) 1rem;
  min-block-size: clamp(15rem, 11rem + 9vw, 20rem);
  display: flex;
  align-items: center;
  justify-content: center;
}

.content-hero__copy {
  inline-size: min(100%, 44rem);
  margin-inline: auto;
  text-align: center;
}

.content-hero__eyebrow {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--content-accent-text);
  margin-block-end: 0.55rem;
}

.content-hero__title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.35rem + 2.4vw, 3.1rem);
  font-weight: 800;
  line-height: 1.25;
  margin: 0 0 0.75rem;
  overflow-wrap: anywhere;
}

/* The introduction is the editor's rich text, so it may be more than one
   paragraph or hold a short list. Paragraphs keep the band's centred reading;
   a list keeps its own start-aligned shape inside it. */
.content-hero__lede {
  color: var(--ink-soft);
  line-height: 1.9;
  margin: 0 auto;
  max-inline-size: 46ch;
  overflow-wrap: anywhere;
}

.content-hero__lede p {
  margin: 0 0 0.5rem;
}

.content-hero__lede > :last-child {
  margin-block-end: 0;
}

.content-hero__lede :where(ul, ol) {
  display: inline-block;
  margin: 0 0 0.5rem;
  padding-inline-start: 1.25rem;
  text-align: start;
}

/* -- the index -------------------------------------------------------------- */

.content-index__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin-block-end: 1.1rem;
}

.content-index__title {
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 800;
  line-height: 1.4;
  margin: 0;
}

/* As many columns as fit a readable card, and never a card wider than the
   screen: `min(100%, ...)` lets a narrow phone fall to one column instead of
   overflowing. */
.content-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17.5rem), 1fr));
  gap: 1.1rem;
}

.content-grid__item {
  display: flex;
  min-inline-size: 0;
}

.content-card {
  position: relative;
  display: flex;
  flex-direction: column;
  inline-size: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
  box-shadow: var(--shadow);
  overflow: hidden;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}

.content-card:hover,
.content-card:focus-within {
  border-color: var(--accent-edge);
  box-shadow: var(--shadow-lg);
}

/* The keyboard ring belongs to the whole card the stretched link covers, the
   way the dashboard's cards draw it. */
.content-card:has(.content-card__link:focus-visible) {
  outline: 3px solid var(--ring);
  outline-offset: 2px;
}

.content-card__link:focus-visible {
  outline: none;
}

.content-card__media {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--content-card-ground);
}

.content-card__image {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.content-card__body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 0.45rem;
  padding: 1rem 1.1rem 1.15rem;
  border-block-start: 1px solid var(--line);
}

.content-card__meta {
  margin: 0;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.content-card__title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 800;
  line-height: 1.65;
  overflow-wrap: anywhere;
}

/* One link with real text, stretched over the whole card: a clickable box with
   no link in it is something a keyboard cannot reach and a screen reader cannot
   name. The chips below it are words, not links. */
.content-card__link {
  color: var(--ink);
  text-decoration: none;
}

.content-card__link::after {
  content: "";
  position: absolute;
  inset: 0;
}

.content-card__link:hover {
  color: var(--accent);
}

.content-card__summary {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.85;
  color: var(--ink-soft);
  overflow-wrap: anywhere;
}

/* The classifications sit at the foot of the card, so a row of cards with
   summaries of different lengths still lines its chips up. */
.content-card__taxonomy {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-block-start: auto;
  padding-block-start: 0.35rem;
}

.content-tags {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.content-tag {
  display: inline-flex;
  align-items: center;
  max-inline-size: 100%;
  padding: 0.12rem 0.6rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  color: var(--ink-soft);
  font-size: 0.76rem;
  font-weight: 700;
  line-height: 1.75;
  overflow-wrap: anywhere;
}

/* A quiet tint per dimension helps the eye group them; each group is also
   named for assistive technology, so the tint is never the only signal. */
.content-tags--families .content-tag {
  border-color: color-mix(in srgb, var(--accent) 40%, var(--line));
  background: color-mix(in srgb, var(--accent) 8%, var(--surface-raised));
  color: var(--content-accent-text);
}

.content-tags--devices .content-tag {
  border-color: color-mix(in srgb, var(--info) 40%, var(--line));
  background: color-mix(in srgb, var(--info) 8%, var(--surface-raised));
  color: var(--ink);
}

.content-index__empty {
  margin: 0;
}

/* -- narrow ----------------------------------------------------------------- */

@media (max-width: 900px) {
  .content-hero::before {
    background-image: var(--content-hero-art-mobile);
    background-position: 50% 8%;
  }

  .content-hero::after {
    background: var(--content-hero-veil-mobile);
  }

  .content-hero__inner {
    min-block-size: clamp(20rem, 15rem + 22vw, 26rem);
    align-items: flex-end;
    padding-block: 1.25rem 1.75rem;
  }
}

@media (max-width: 640px) {
  .content-grid {
    gap: 0.85rem;
  }

  .content-card__body {
    padding: 0.9rem 0.95rem 1rem;
  }
}

/* ---------------------------------------------- UX-8A homepage discovery --- */
/*
 * The homepage's way into the article and tutorial sections: one large card per
 * section, picture above and words below, so the words never sit on artwork and
 * their contrast does not depend on it. The whole card is the one link it holds.
 * Two cards share a row on a desktop and stack on a phone; a single card takes
 * the row.
 */

.discovery__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
}

.discovery__item {
  display: flex;
  min-inline-size: 0;
}

.discovery-card {
  position: relative;
  display: flex;
  flex-direction: column;
  inline-size: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}

/* The lit top edge the capability cards above carry. */
.discovery-card::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 1px;
  background: var(--edge);
  opacity: 0.75;
  z-index: 1;
}

.discovery-card:hover,
.discovery-card:focus-within {
  border-color: var(--accent-edge);
}

.discovery-card:has(.discovery-card__link:focus-visible) {
  outline: 3px solid var(--ring);
  outline-offset: 2px;
}

.discovery-card__link:focus-visible {
  outline: none;
}

.discovery-card__art {
  aspect-ratio: 16 / 7;
  background-color: var(--surface-sunken);
  background-size: cover;
  background-repeat: no-repeat;
  border-block-end: 1px solid var(--line);
}

.discovery-card--articles .discovery-card__art {
  background-image: var(--discovery-articles-art);
  background-position: var(--discovery-articles-position);
}

.discovery-card--tutorials .discovery-card__art {
  background-image: var(--discovery-tutorials-art);
  background-position: var(--discovery-tutorials-position);
}

.discovery-card__body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.55rem;
  padding: 0 1.4rem 1.35rem;
}

/* The section's mark rides the seam between picture and words. */
.discovery-card__mark {
  position: relative;
  display: grid;
  place-items: center;
  inline-size: 2.9rem;
  block-size: 2.9rem;
  margin-block-start: -1.45rem;
  border-radius: 0.9rem;
  border: 1px solid var(--accent-edge);
  background: var(--surface-raised);
  color: var(--accent);
  box-shadow: var(--glow-soft), var(--shadow);
}

.discovery-card__mark svg {
  inline-size: 1.35rem;
  block-size: 1.35rem;
}

.discovery-card__title {
  margin: 0.2rem 0 0;
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 800;
  line-height: 1.45;
  overflow-wrap: anywhere;
}

.discovery-card__text {
  margin: 0;
  color: var(--ink-soft);
  line-height: 1.85;
}

/* A real link with a real name, stretched over the card, and tall enough to be
   an honest touch target where it is drawn. */
.discovery-card__link {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  min-block-size: 2.75rem;
  margin-block-start: auto;
  padding-block-start: 0.35rem;
  font-weight: 700;
  color: var(--content-accent-text);
  text-decoration: none;
}

.discovery-card__link::after {
  content: "";
  position: absolute;
  inset: 0;
}

.discovery-card__link:hover {
  text-decoration: underline;
}

.discovery-card__link svg {
  inline-size: 1.1rem;
  block-size: 1.1rem;
  flex: none;
}

[dir="rtl"] .discovery-card__link svg {
  transform: scaleX(-1);
}

@media (max-width: 640px) {
  .discovery-card__art {
    aspect-ratio: 16 / 9;
  }

  .discovery-card--articles .discovery-card__art {
    background-image: var(--discovery-articles-art-mobile);
  }

  .discovery-card--tutorials .discovery-card__art {
    background-image: var(--discovery-tutorials-art-mobile);
  }

  .discovery-card__body {
    padding: 0 1.1rem 1.1rem;
  }
}

/* ------------------------------------------ UX-8B editorial detail pages --- */
/*
 * A tutorial reads as one calm column under the same lead band the indexes use:
 * the path back up the tree, what the tutorial is classified as, its lead
 * picture, then the body - text at a readable measure, pictures in quiet frames,
 * callouts that name their meaning, and a procedure whose numbers are joined by a
 * rail. No block is a card inside a card, and nothing glows but the step numbers.
 *
 * The body blocks are shared with articles, so `.reading-body` and everything
 * inside it style an article's heading, text, picture and callout the same way.
 * Everything is placed with logical properties: one set of rules for Persian and
 * English.
 */

.guide {
  max-inline-size: 48rem;
  margin-inline: auto;
}

.guide__lead {
  display: grid;
  gap: 1.1rem;
  margin-block-end: 2.25rem;
}

/* A tutorial's title is a sentence, often a long one. Over the index band's veil a
   title of several lines spread onto the brightest parts of the artwork, so on a
   detail page the words sit on a quiet panel of the page's own surface - the glass
   the capability cards use, made nearly opaque - and the title is set smaller. The
   artwork still frames the lead; it no longer decides whether the text can be read. */
.content-hero--detail .content-hero__copy {
  padding: clamp(1rem, 0.6rem + 1.5vw, 1.6rem) clamp(1rem, 0.5rem + 2vw, 2rem);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--surface-raised) 86%, transparent);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: var(--shadow-lg);
}

.content-hero--detail .content-hero__title {
  font-size: clamp(1.6rem, 1.2rem + 1.2vw, 2.15rem);
  line-height: 1.45;
}

.content-hero--detail .content-hero__lede {
  max-inline-size: 60ch;
}

/* -- the path back up the tree ------------------------------------------------ */

.reading-crumbs {
  margin: 0;
}

.reading-crumbs__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.5rem;
}

.reading-crumbs__item {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

/* The separator is drawn, and its alternative text is empty, so a screen reader
   hears the places and not the punctuation between them. */
.reading-crumbs__item + .reading-crumbs__item::before {
  content: "/" / "";
  color: var(--line-strong);
}

.reading-crumbs a {
  display: inline-flex;
  align-items: center;
  min-block-size: 2rem;
}

/* -- what the tutorial is classified as -------------------------------------- */

.reading-meta {
  margin: 0;
  display: grid;
  gap: 0.65rem;
  padding: 0.95rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
}

.reading-meta__group {
  display: grid;
  grid-template-columns: minmax(0, 11rem) minmax(0, 1fr);
  align-items: baseline;
  gap: 0.35rem 1rem;
}

.reading-meta__group dt {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--ink-soft);
}

.reading-meta__group dd {
  margin: 0;
  min-inline-size: 0;
}

/* -- pictures ------------------------------------------------------------------ */

.reading-figure {
  margin: 0;
  min-inline-size: 0;
}

/* A picture is shown at its own size or smaller, never stretched, and never taller
   than the reader can take in at once: a tall screenshot scales down whole rather
   than filling several screens. Width and height come from the markup, so the
   browser keeps the proportions and reserves the space before it loads. */
.reading-figure__image {
  display: block;
  inline-size: auto;
  max-inline-size: 100%;
  block-size: auto;
  max-block-size: 40rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-sunken);
}

.reading-figure--lead .reading-figure__image {
  box-shadow: var(--shadow-lg);
}

.reading-figure--step .reading-figure__image {
  max-block-size: 30rem;
  border-radius: var(--radius);
}

.reading-figure__caption {
  margin-block-start: 0.55rem;
  font-size: 0.86rem;
  line-height: 1.85;
  color: var(--ink-soft);
  overflow-wrap: anywhere;
}

/* -- the body ------------------------------------------------------------------ */

.reading-body {
  display: grid;
  gap: 1.15rem;
  min-inline-size: 0;
}

.reading-body > * {
  margin: 0;
  min-inline-size: 0;
}

.reading-body__heading {
  margin-block-start: 1rem;
  overflow-wrap: anywhere;
}

/* Rich text an editor wrote: paragraphs, lists and links. One rule set for every
   place it appears - body text, a callout, a procedure's introduction, a step. */
:where(.reading-body__text, .steps__intro, .step__body, .callout__body) {
  line-height: 2;
  overflow-wrap: anywhere;
}

:where(.reading-body__text, .steps__intro, .step__body, .callout__body) > * {
  margin-block: 0 0.75rem;
}

:where(.reading-body__text, .steps__intro, .step__body, .callout__body) > :last-child {
  margin-block-end: 0;
}

:where(.reading-body__text, .steps__intro, .step__body, .callout__body) :where(ul, ol) {
  padding-inline-start: 1.5rem;
}

:where(.reading-body__text, .steps__intro, .step__body, .callout__body) li {
  margin-block-end: 0.3rem;
}

:where(.reading-body__text, .steps__intro, .step__body, .callout__body) li::marker {
  color: var(--content-accent-text);
}

:where(.reading-body__text, .steps__intro, .step__body, .callout__body) a {
  color: var(--content-accent-text);
  text-decoration: underline;
  text-underline-offset: 0.22em;
}

/* -- callouts ------------------------------------------------------------------ */

.callout {
  --callout-tone: var(--info);
  --callout-tint: var(--info-tint);
  display: grid;
  gap: 0.35rem;
  padding: 0.85rem 1.1rem 0.95rem;
  border: 1px solid color-mix(in srgb, var(--callout-tone) 30%, var(--line));
  border-inline-start: 4px solid var(--callout-tone);
  border-radius: var(--radius);
  background: var(--callout-tint);
}

.callout--tip {
  --callout-tone: var(--ok);
  --callout-tint: var(--ok-tint);
}

.callout--warning {
  --callout-tone: var(--warn);
  --callout-tint: var(--warn-tint);
}

.callout__label {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0;
  font-size: 0.9rem;
  font-weight: 800;
  color: var(--callout-tone);
}

.callout__label svg {
  inline-size: 1.15rem;
  block-size: 1.15rem;
  flex: none;
}

.callout__body {
  color: var(--ink);
}

/* -- a procedure --------------------------------------------------------------- */

.steps {
  display: grid;
  gap: 1rem;
  margin-block-start: 0.75rem;
}

.steps__label {
  margin: 0;
}

.steps__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
}

.step {
  position: relative;
  display: grid;
  grid-template-columns: 2.6rem minmax(0, 1fr);
  gap: 0 1rem;
  padding-block-end: 1.75rem;
}

.step:last-child {
  padding-block-end: 0;
}

/* The rail from one number down to the next. It ends before the last step, so a
   procedure visibly finishes where it does. */
.step::before {
  content: "";
  position: absolute;
  inset-inline-start: calc(1.3rem - 1px);
  inset-block: 2.85rem 0.35rem;
  inline-size: 2px;
  border-radius: 2px;
  background: linear-gradient(var(--accent-edge), color-mix(in srgb, var(--accent-edge) 25%, transparent));
}

.step:last-child::before {
  display: none;
}

.step__number {
  display: grid;
  place-items: center;
  inline-size: 2.6rem;
  block-size: 2.6rem;
  border: 1px solid var(--accent-edge);
  border-radius: 50%;
  background: var(--surface-raised);
  color: var(--content-accent-text);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  box-shadow: var(--glow-soft);
}

.step__content {
  display: grid;
  gap: 0.55rem;
  min-inline-size: 0;
  padding-block-start: 0.4rem;
}

.step__title {
  margin: 0;
  font-size: 1.1rem;
  overflow-wrap: anywhere;
}

/* -- controlled external video (SCS-P08) ----------------------------------------- */

/* A YouTube or Aparat embed whose address the application builds from the provider
   and the canonical video id. A steady 16:9 frame, sized like a step picture, so the
   layout is reserved before the provider's document loads; the iframe is its own
   document and nothing here reaches into it. */
.external-video {
  position: relative;
  inline-size: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-sunken);
}

.external-video__frame {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  border: 0;
}

/* -- uploaded video (SCS-P10) ---------------------------------------------------- */

/* The browser's own video controls in the same reserved 16:9 frame as an external
   video: full inline width, bounded by the step column, never wider than the screen.
   `object-fit: contain` letterboxes a video of another shape instead of cropping it. */
.uploaded-video {
  inline-size: 100%;
  max-inline-size: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-sunken);
}

.uploaded-video__player {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
}

/* -- related products ---------------------------------------------------------- */

/* Names only. What a tutorial is written about is not an offer: no price, no
   availability and no way to buy lives here. */
.reading-related {
  margin-block-start: 2.5rem;
  padding-block-start: 1.5rem;
  border-block-start: 1px solid var(--line);
}

.reading-related__title {
  margin: 0 0 0.3rem;
  font-size: 1.1rem;
}

.reading-related__note {
  margin: 0 0 0.8rem;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.reading-related__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.reading-related__list > li {
  max-inline-size: 100%;
  padding: 0.15rem 0.75rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  font-size: 0.86rem;
  font-weight: 700;
  line-height: 1.8;
  overflow-wrap: anywhere;
}

@media (max-width: 640px) {
  .reading-meta__group {
    grid-template-columns: minmax(0, 1fr);
  }

  .step {
    grid-template-columns: 2.2rem minmax(0, 1fr);
    gap: 0 0.75rem;
  }

  .step::before {
    inset-inline-start: calc(1.1rem - 1px);
    inset-block-start: 2.45rem;
  }

  .step__number {
    inline-size: 2.2rem;
    block-size: 2.2rem;
  }
}

/* --------------------------------------------------- UX-8C an article --- */
/*
 * An article uses the tutorial's reading system - the detail band, the path back
 * up the tree, the shared body blocks - and leans a little further towards
 * editorial reading: a slightly narrower column, a touch larger text, a dateline
 * under the path, and body headings marked with a short accent rule. Every rule
 * here is scoped to `.story`, so the accepted tutorial page is unchanged.
 */

.story {
  max-inline-size: 46rem;
  margin-inline: auto;
}

.story__lead {
  display: grid;
  gap: 1rem;
  margin-block-end: 2.25rem;
}

/* The dateline: the editorial date the article holds, then its subjects. A quiet
   row between two hairlines, wrapping to two lines on a phone rather than
   squeezing either part. */
.story-dateline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.55rem 1.1rem;
  padding-block: 0.75rem;
  border-block: 1px solid var(--line);
}

.story-dateline__date {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.2rem 0.4rem;
  margin: 0;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.story-dateline__date svg {
  inline-size: 1.05rem;
  block-size: 1.05rem;
  flex: none;
  color: var(--content-accent-text);
}

.story-dateline__label {
  font-weight: 700;
}

.story-dateline__subjects {
  flex: 1 1 14rem;
  min-inline-size: 0;
}

.story .reading-body__text {
  font-size: 1.05rem;
}

.story .reading-body__heading {
  padding-inline-start: 0.85rem;
  border-inline-start: 3px solid var(--accent);
}

/* ---------------------------------------- UX10-A account, titles, pager --- */
/*
 * UX10-A foundations and their visual correction. Tokens only, in the existing
 * card and glow language. Game tiles are artwork-first: the picture is the card
 * and a short caption sits on a dark scrim at its foot, in both themes, because
 * the scrim belongs to the artwork rather than to the page around it.
 */

/* The header identity is the way to the profile. */
a.session-user {
  text-decoration: none;
  transition: border-color 160ms ease, color 160ms ease;
}

a.session-user:hover,
a.session-user[aria-current="page"] {
  border-color: var(--accent-edge);
  color: var(--ink);
}

.messages li.info {
  border-inline-start: 3px solid var(--info);
  background: var(--info-tint);
  color: var(--ink);
}

/* EMAIL-VERIFY-COOLDOWN-01. Action feedback tagged "toast". In the message list (no script)
   its paragraphs keep their breaks; toast.js lifts it into this corner region: a raised card
   with the message level's edge, a real close button, never a modal or an overlay. It sits at
   the reading end of the bottom edge and spans the width on a phone, above page content but
   below the site header's own layers, and it does not move. */
.messages li.toast,
.toast__text {
  white-space: pre-line;
}

.toast-region {
  position: fixed;
  inset-block-end: 1rem;
  inset-inline-end: 1rem;
  z-index: 45;
  display: grid;
  gap: 0.5rem;
  inline-size: min(26rem, calc(100vw - 2rem));
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--line-strong);
  border-inline-start: 4px solid var(--info);
  border-radius: var(--radius);
  background: var(--surface-raised);
  color: var(--ink);
  box-shadow: var(--shadow-lg);
}

.toast.success {
  border-inline-start-color: var(--ok);
}

.toast__text {
  flex: 1 1 auto;
  min-inline-size: 0;
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.7;
}

.toast__close {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  inline-size: 2rem;
  block-size: 2rem;
  margin: -0.3rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink-soft);
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
}

.toast__close:hover {
  background: var(--surface-sunken);
  color: var(--ink);
}

@media (max-width: 640px) {
  .toast-region {
    inset-inline: 0.75rem;
    inset-block-end: 0.75rem;
    inline-size: auto;
  }
}

/* -- profile and security -- */
.profile-head {
  display: flex;
  align-items: center;
  gap: 0.9rem;
}

.profile-head h1 {
  margin: 0;
}

.profile-head p {
  margin: 0.2rem 0 0;
}

.profile-head__avatar {
  display: grid;
  flex: 0 0 auto;
  place-items: center;
  width: 3.1rem;
  height: 3.1rem;
  border-radius: 50%;
  border: 1px solid var(--accent-edge);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 1.3rem;
  font-weight: 800;
  line-height: 1;
}

.profile-head__avatar--icon svg {
  width: 1.45rem;
  height: 1.45rem;
}

.profile-layout {
  display: grid;
  gap: var(--gap);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}

@media (min-width: 900px) {
  .profile-layout {
    grid-template-columns: minmax(15rem, 1fr) minmax(0, 2.2fr);
  }
}

.profile-aside {
  display: grid;
  gap: var(--gap);
}

.profile-card {
  margin-bottom: 0;
}

.profile-card__title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.9rem;
  font-size: 1.05rem;
}

.profile-card__icon {
  width: 1.2rem;
  height: 1.2rem;
  color: var(--accent);
  flex: 0 0 auto;
}

.profile-card__note,
.profile-fieldset__note {
  margin: 0.6rem 0 0;
}

.profile-security {
  border-inline-start: 3px solid var(--accent-edge);
}

.profile-security__action {
  margin-top: 0.9rem;
  min-height: 2.75rem;
}

/* EMAIL-VERIFY-COOLDOWN-01. The unverified-address card, scannable rather than a stack of
   paragraphs: where the email goes (in the ordinary ink - it is a fact, not a hint), one short
   Spam/Junk hint, the wait as a single line, the action, then two small notes under a hairline.
   The hints and notes take --verification-hint-text, a readable text colour each theme sets. */
.profile-verification__address {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.1rem 0.4rem;
  margin: 0.6rem 0 0;
  font-size: 0.85rem;
}

.profile-verification__label {
  color: var(--ink-soft);
}

.profile-verification__email {
  color: var(--ink);
  font-weight: 700;
  overflow-wrap: anywhere;
}

.profile-verification__hint {
  margin: 0.5rem 0 0;
  color: var(--verification-hint-text);
  font-size: 0.8rem;
  line-height: 1.65;
}

.profile-verification__hint a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.profile-verification__wait {
  margin: 0.55rem 0 0;
  color: var(--ink-soft);
  font-size: 0.82rem;
}

.profile-verification__wait strong {
  color: var(--ink);
}

.profile-verification__action {
  margin-top: 0.7rem;
}

.profile-verification__notes {
  display: grid;
  gap: 0.2rem;
  margin: 0.75rem 0 0;
  padding: 0.6rem 0 0;
  list-style: none;
  border-top: 1px solid var(--line);
}

.profile-verification__notes .profile-verification__hint {
  margin: 0;
}

.profile-back {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 2.75rem;
  margin-bottom: 0.6rem;
  font-weight: 600;
}

.profile-back svg {
  width: 1.1rem;
  height: 1.1rem;
}

[dir="rtl"] .profile-back svg {
  transform: scaleX(-1);
}

.profile-password {
  max-width: 34rem;
}

.profile-identity {
  margin: 0;
}

.profile-identity__row dt {
  font-size: 0.82rem;
  color: var(--ink-soft);
}

.profile-identity__row dd {
  margin: 0.2rem 0 0;
  font-weight: 700;
  overflow-wrap: anywhere;
}

.profile-fieldset {
  margin: 0 0 1.1rem;
  padding: 0;
  border: 0;
  min-width: 0;
}

.profile-fieldset legend {
  margin-bottom: 0.7rem;
  padding: 0;
  font-weight: 700;
  color: var(--ink);
}

.profile-fieldset__grid {
  display: grid;
  gap: 0 1rem;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 640px) {
  .profile-fieldset__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* -- platform glyphs, shared by filters and cards -- */
.platform-icon {
  width: 1.1rem;
  height: 1.1rem;
  flex: 0 0 auto;
}

/* A brand's own platform mark, when the deployment ships one. Every mark gets the
   same square box and is contained in it - never stretched to fill it - because a
   trademark is a shape with proportions, and the one thing worse than not showing
   it is showing it squashed. The box is what makes six different logos read as
   one row: the same footprint, each drawn at its own shape inside. */
img.platform-icon--mark {
  object-fit: contain;
  object-position: center;
}

/* One of a light/dark pair. Exactly one is displayed, chosen by the tokens the
   theme blocks set, so an explicit choice in the theme switch and the operating
   system's preference are both honoured and the two never show together. Both are
   in the page from the first paint with the same box, so switching theme swaps a
   picture without moving anything. */
.platform-icon--light-theme {
  display: var(--display-light-theme, inline-block);
}

.platform-icon--dark-theme {
  display: var(--display-dark-theme, none);
}

/* A single-colour vector mark is placed in the page as markup, so it follows the
   control's colour like any glyph - muted at rest, brighter on hover, the accent
   when selected. */
svg.platform-icon--vector {
  overflow: visible;
}

/* The Type filter's glyph. Smaller than a platform mark on purpose: Type is the
   secondary filter and should not read as loudly as the row above it. */
.type-icon {
  width: 1rem;
  height: 1rem;
  flex: 0 0 auto;
}

/* -- landing: featured supported titles -- */
.featured-titles {
  position: relative;
  isolation: isolate;
  margin-block: 2.5rem;
  padding: 2.2rem 1.2rem 2rem;
  border: 1px solid var(--line);
  border-radius: calc(var(--radius-lg) * 1.4);
  background:
    radial-gradient(60% 80% at 15% 0%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 70%),
    radial-gradient(50% 70% at 90% 100%, color-mix(in srgb, var(--accent-2) 18%, transparent), transparent 70%),
    var(--surface-raised);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.featured-titles::before {
  content: "";
  position: absolute;
  inset-inline: 8%;
  top: 0;
  height: 1px;
  z-index: 1;
  background: linear-gradient(90deg, transparent, var(--accent), var(--accent-2), transparent);
  opacity: 0.8;
}

/* UX10-A correction 02. The shelf stands on a brand's own stage rather than on a
   gradient: the artwork goes behind everything, under its brand's veil, and the
   real game covers an operator uploaded stay the brightest thing in the section.
   With no artwork the layer paints nothing and the panel is exactly what it was. */
.featured-titles::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--featured-veil), var(--featured-art);
  background-size: cover, cover;
  background-position: center, 50% 18%;
  background-repeat: no-repeat, no-repeat;
  pointer-events: none;
}

@media (max-width: 719px) {
  .featured-titles::after {
    background-image: var(--featured-veil), var(--featured-art-narrow);
  }
}

.featured-titles__inner {
  position: relative;
  z-index: 1;
}

.featured-titles__head {
  margin-bottom: 1.4rem;
  text-align: center;
}

.featured-titles__kicker {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.5rem 0.75rem;
  margin: 0;
}

.featured-titles__eyebrow {
  display: inline-block;
  padding: 0.15rem 0.75rem;
  border: 1px solid var(--accent-edge);
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.78rem;
  font-weight: 800;
}

.featured-titles__sub {
  color: var(--ink-soft);
  font-size: 0.92rem;
}

/* The headline is the section, so it gets the room: balanced wrapping on a
   phone, and one line from the width where one line actually fits. */
.featured-titles__title {
  margin: 0.55rem 0 0;
  font-size: clamp(1.4rem, 1rem + 1.6vw, 2.15rem);
  line-height: 1.35;
  text-wrap: balance;
  text-shadow: var(--hero-ink-shadow);
}

@media (min-width: 1100px) {
  .featured-titles__title {
    white-space: nowrap;
  }
}

.featured-rail {
  margin-inline: -1.2rem;
  padding: 0.4rem 1.2rem 0.8rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: thin;
}

.featured-rail:focus-visible {
  outline: 3px solid var(--focus, var(--accent));
  outline-offset: -3px;
}

.featured-rail__track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(8.5rem, 42%);
  gap: 0.8rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.featured-rail__item {
  scroll-snap-align: start;
}

@media (min-width: 720px) {
  .featured-rail {
    overflow: visible;
  }

  .featured-rail__track {
    grid-auto-flow: row;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1rem;
  }
}

@media (min-width: 1100px) {
  .featured-rail__track {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
}

.featured-titles__action {
  display: flex;
  justify-content: center;
  margin-top: 1.4rem;
}

.featured-titles__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.9rem;
  padding-inline: 1.4rem;
  border-radius: var(--radius-pill);
}

.featured-titles__cta svg {
  width: 1.25rem;
  height: 1.25rem;
}

/* A featured game: the artwork is the tile, the name sits on its own scrim. */
.game-tile {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--media-ground);
  box-shadow: var(--media-shadow);
  isolation: isolate;
  transition: transform 180ms ease, box-shadow 180ms ease;
}

.game-tile::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  border: 1px solid var(--media-edge);
  background: var(--media-scrim);
  pointer-events: none;
}

.game-tile::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  z-index: 2;
  height: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  opacity: 0;
  transition: opacity 180ms ease;
}

.game-tile:hover {
  transform: translateY(-4px);
  box-shadow: var(--media-shadow-hover), 0 0 0 1px var(--accent-edge);
}

.game-tile:hover::after {
  opacity: 1;
}

.game-tile__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.game-tile__name {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  z-index: 2;
  padding: 0.7rem 0.75rem 0.8rem;
  color: var(--media-ink);
  font-weight: 800;
  font-size: 0.95rem;
  line-height: 1.35;
  text-shadow: var(--media-ink-shadow);
  overflow-wrap: anywhere;
}

/* -- supported titles: the discovery control -- */
.discovery-control {
  position: relative;
  display: grid;
  gap: 1rem;
  margin-bottom: 1.6rem;
  padding: 1.1rem;
  border: 1px solid var(--line);
  border-radius: calc(var(--radius-lg) * 1.3);
  background:
    radial-gradient(70% 120% at 0% 0%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 65%),
    radial-gradient(60% 120% at 100% 100%, color-mix(in srgb, var(--accent-2) 12%, transparent), transparent 65%),
    var(--surface-raised);
  box-shadow: var(--shadow-lg);
}

.discovery-control::before {
  content: "";
  position: absolute;
  inset-inline: 6%;
  top: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent), var(--accent-2), transparent);
  opacity: 0.7;
}

/* A grid item's minimum width is its content's by default, and a search input's
   content is a fixed number of characters wide - enough, below about 375 px, to push
   the whole page sideways. The field shrinks with the control instead. */
.discovery-search {
  min-width: 0;
}

.discovery-search__field {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 3.25rem;
  padding: 0.3rem;
  padding-inline-start: 0.85rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  transition: border-color 160ms ease, box-shadow 160ms ease;
}

.discovery-search__field:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent);
}

.discovery-search__icon {
  width: 1.25rem;
  height: 1.25rem;
  color: var(--ink-faint);
  flex: 0 0 auto;
}

.discovery-search__field input[type="search"] {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 2.6rem;
  padding: 0 0.3rem;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  outline: none;
}

.discovery-search__field input[type="search"]::placeholder {
  color: var(--ink-faint);
}

.discovery-search__submit {
  flex: 0 0 auto;
  min-height: 2.6rem;
  padding-inline: 1.3rem;
  border-radius: var(--radius-pill);
}

.discovery-filters {
  display: grid;
  gap: 0.9rem;
}

@media (min-width: 900px) {
  .discovery-filters {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
  }
}

.discovery-group {
  min-width: 0;
}

.discovery-group__label {
  margin: 0 0 0.45rem;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: var(--tracking-eyebrow);
  color: var(--ink-faint);
}

/* UX10-A correction 05. The platform row is marks, not words: six controls that
   fit one line on a phone, each square enough to be a comfortable target and to
   hold a mark at a size worth looking at. The name is still in the markup, still
   the control's accessible name, and still its tooltip - it is only not drawn. */
.platform-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.platform-tab,
.type-segment {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-width: 3.25rem;
  min-height: 2.75rem;
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  color: var(--ink-soft);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}

.platform-tab:hover,
.type-segment:hover {
  border-color: var(--accent-edge);
  color: var(--ink);
}

.platform-tab--selected,
.type-segment--selected {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, var(--surface-sunken));
  color: var(--ink);
  font-weight: 800;
  box-shadow: inset 0 -2px 0 var(--accent);
}

.platform-tab--selected .platform-icon {
  color: var(--accent);
}

/* UX10-A correction 02. The platform row is the primary filter, so its mark is
   drawn larger than a caption glyph and the name sits beside it rather than
   under it. The name never leaves: a mark alone is unreadable to a screen
   reader and ambiguous to anybody who does not own that console. */
.platform-tab .platform-icon {
  width: 1.5rem;
  height: 1.5rem;
}

/* In the filter the marks are the whole face of the control, so they are drawn
   larger than a glyph, in the same box, and the full-colour ones lift a little on
   hover and when chosen - a step in presence rather than a change of colour,
   which would be a recolouring of somebody else's mark. */
.platform-tab .platform-icon--mark,
.platform-tab .platform-icon--vector {
  width: 1.75rem;
  height: 1.75rem;
}

.platform-tab img.platform-icon--mark {
  opacity: 0.86;
  transform: scale(var(--mark-optical-scale, 1));
  transition: opacity 160ms ease, transform 160ms ease;
}

.platform-tab:hover img.platform-icon--mark,
.platform-tab:focus-visible img.platform-icon--mark,
.platform-tab--selected img.platform-icon--mark {
  opacity: 1;
  transform: scale(calc(var(--mark-optical-scale, 1) * 1.06));
}

/* Six marks on one line on a phone: a narrower box that is still a 44 px touch
   target, rather than five on one line and Mobile stranded on the next. */
@media (max-width: 479px) {
  .platform-tabs {
    gap: 0.35rem;
  }

  .platform-tab {
    min-width: 2.75rem;
    padding-inline: 0.35rem;
  }
}

/* Optical sizing. Every mark sits in the same box, but supplied artwork arrives
   with its own margins and its own shape - a wide, short mark reads smaller than a
   round one of the same box. A brand that ships marks may say how much larger one
   should be drawn to carry the same weight as its neighbours; the default is
   "exactly as supplied", and this sheet names no brand and no value. Scaling is
   uniform, so a mark is never stretched to make it fit. */
.platform-icon--group-pc {
  --mark-optical-scale: var(--platform-mark-scale-pc, 1);
}

.platform-icon--group-playstation {
  --mark-optical-scale: var(--platform-mark-scale-playstation, 1);
}

.platform-icon--group-xbox {
  --mark-optical-scale: var(--platform-mark-scale-xbox, 1);
}

.platform-icon--group-nintendo {
  --mark-optical-scale: var(--platform-mark-scale-nintendo, 1);
}

.platform-icon--group-mobile {
  --mark-optical-scale: var(--platform-mark-scale-mobile, 1);
}

.type-segment .type-icon {
  width: 1.2rem;
  height: 1.2rem;
}

.type-segment--selected .type-icon {
  color: var(--accent);
}

/* The selected control is marked by a shape, not only by its colour: a tick in
   the corner that is there or is not, on top of the filled treatment below. */
.platform-tab__check,
.type-segment__check {
  position: absolute;
  inset-block-start: -0.35rem;
  inset-inline-end: -0.35rem;
  width: 1.1rem;
  height: 1.1rem;
  padding: 0.14rem;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-contrast);
  box-shadow: 0 0 0 2px var(--surface-raised);
}

.type-segments {
  display: inline-grid;
  grid-template-columns: repeat(3, auto);
  gap: 0;
  margin: 0;
  padding: 0.2rem;
  list-style: none;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-sunken);
}

.type-segment {
  min-width: 3rem;
  min-height: 2.5rem;
  border-color: transparent;
  background: transparent;
}

/* Inside a segmented control there is no room outside the button for a corner
   badge, so the tick sits in the top corner of the segment itself. */
.type-segment__check {
  inset-block-start: -0.25rem;
  inset-inline-end: -0.25rem;
  box-shadow: 0 0 0 2px var(--surface-sunken);
}

/* -- supported titles: results and cards -- */
.titles-results__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.9rem;
}

.titles-results__title {
  margin: 0;
  font-size: 1.15rem;
}

.titles-results__count {
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.9rem;
}

/* 50 a page: five columns on a large desktop, fewer as space runs out. */
.titles-grid {
  display: grid;
  gap: 0.85rem;
  margin: 0;
  padding: 0;
  list-style: none;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 640px) {
  .titles-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 900px) {
  .titles-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1rem;
  }
}

@media (min-width: 1100px) {
  .titles-grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

.title-card {
  height: 100%;
}

.title-card__media {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--media-ground);
  box-shadow: var(--media-shadow);
  isolation: isolate;
  transition: transform 180ms ease, box-shadow 180ms ease;
}

.title-card__media::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  border: 1px solid var(--media-edge);
  background: var(--media-scrim);
  pointer-events: none;
}

.title-card:hover .title-card__media {
  transform: translateY(-3px);
  box-shadow: var(--media-shadow-hover), 0 0 0 1px var(--accent-edge);
}

.title-card__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.title-card--temporarily_unavailable .title-card__art {
  filter: grayscale(0.85) brightness(0.72);
}

.title-card--coming_soon .title-card__art {
  filter: saturate(0.7) brightness(0.85);
}

/* Missing artwork is shown as missing - never dressed up as a finished tile. */
.title-card__fallback {
  position: absolute;
  inset: 0.55rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  padding-bottom: 30%;
  border: 1px dashed var(--media-fallback-edge);
  border-radius: var(--radius);
  background: repeating-linear-gradient(135deg, var(--media-fallback-hatch) 0 10px, transparent 10px 20px);
  color: var(--media-fallback-ink);
  font-size: 0.74rem;
  text-align: center;
}

.title-card__fallback svg {
  width: 1.8rem;
  height: 1.8rem;
}

.title-card__status {
  position: absolute;
  top: 0.55rem;
  inset-inline-start: 0.55rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin: 0;
  padding: 0.2rem 0.6rem;
  border-radius: var(--radius-pill);
  font-size: 0.74rem;
  font-weight: 800;
  line-height: 1.5;
  color: var(--media-ink);
  background: var(--media-status-soon);
  box-shadow: var(--media-status-shadow);
}

.title-card--temporarily_unavailable .title-card__status {
  background: var(--media-status-paused);
}

.title-card__status svg {
  width: 0.9rem;
  height: 0.9rem;
  flex: 0 0 auto;
}

.title-card__caption {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  z-index: 2;
  display: grid;
  gap: 0.25rem;
  padding: 0.6rem 0.65rem 0.65rem;
  color: var(--media-ink);
}

.title-card__name {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 800;
  line-height: 1.3;
  color: var(--media-ink);
  text-shadow: var(--media-ink-shadow);
  overflow-wrap: anywhere;
}

.title-card__type {
  margin: 0;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--media-ink-soft);
}

/* UX10-A correction 02. One line, never two: the badges sit in the artwork's own
   scrim beside the name, and a title supported on every platform makes its card
   no taller than a title supported on one. The row's accessible name lists all
   of them in full, so the cap is a visual one only. */
.title-card__platforms {
  display: flex;
  flex-wrap: nowrap;
  gap: 0.25rem;
  margin: 0.15rem 0 0;
  padding: 0;
  list-style: none;
  overflow: hidden;
}

.platform-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  padding: 0.08rem 0.4rem;
  border: 1px solid var(--media-chip-edge);
  border-radius: var(--radius-pill);
  background: var(--media-chip-ground);
  color: var(--media-chip-ink);
  font-size: 0.68rem;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}

.platform-chip .platform-icon {
  width: 0.85rem;
  height: 0.85rem;
  color: var(--accent);
}

.platform-chip img.platform-icon--mark {
  width: 0.95rem;
  height: 0.95rem;
}

/* A card caption always sits on the artwork's own dark scrim, whatever the page
   theme is, so a light/dark pair on a card always shows its dark-page member: the
   light-page PlayStation mark is drawn in black and would vanish on that scrim. */
.title-card__platforms {
  --display-light-theme: none;
  --display-dark-theme: inline-block;
}

/* "+2" - the visual short form of platforms the row already named out loud. */
.platform-chip--more {
  font-variant-numeric: tabular-nums;
}

/* Two cards to a phone screen leaves a card about as wide as four badges with
   their generation labels on. The labels go and the marks stay, because the row
   says all of it in full to a screen reader either way - and a clipped label is
   worse than no label. */
@media (max-width: 639px) {
  .platform-chip__text {
    display: none;
  }
}

.titles-empty {
  margin-top: 0.5rem;
}

.titles-note {
  margin-top: 1.4rem;
}

/* -- the shared public pager -- */
.pager--public {
  justify-content: center;
  margin-block-start: 1.5rem;
}

.pager--public .btn {
  min-height: 2.75rem;
}

@media (prefers-reduced-motion: reduce) {
  .game-tile,
  .title-card__media,
  .platform-tab img.platform-icon--mark {
    transition: none;
  }

  .platform-tab:hover img.platform-icon--mark,
  .platform-tab:focus-visible img.platform-icon--mark,
  .platform-tab--selected img.platform-icon--mark {
    transform: none;
  }

  .game-tile:hover,
  .title-card:hover .title-card__media {
    transform: none;
  }
}

/* -- the operator's Supported Titles list (UX10-OPS-01) -- */
/*
 * A working list, not a gallery: a small cover so an operator recognises the
 * row at a glance, the facts that matter beside it, and every routine action in
 * reach. The Staff shell's own table styles do the rest, so this is only what a
 * list of pictures needs that a list of numbers does not.
 */

.titles-admin__lead {
  display: flex;
  align-items: center;
  gap: 0.65rem;
}

.titles-admin__lead > span {
  display: grid;
  gap: 0.15rem;
  min-width: 0;
}

.titles-admin__thumb {
  flex: 0 0 auto;
  width: 2.25rem;
  height: 3rem;
  border-radius: calc(var(--radius) * 0.6);
  border: 1px solid var(--line);
  object-fit: cover;
  background: var(--surface-sunken);
}

/* A row with no cover shows that it has none, rather than an empty frame that
   could be mistaken for a picture that failed to load. */
.titles-admin__thumb--empty {
  display: block;
  border-style: dashed;
}

.titles-admin__platforms {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

.titles-admin__move {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.btn.titles-admin__arrow {
  min-width: 2.25rem;
  padding-inline: 0.5rem;
}

.titles-admin__arrow svg {
  width: 1rem;
  height: 1rem;
}

.titles-admin__artwork {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin-block-end: 0.9rem;
}

.titles-admin__preview {
  flex: 0 0 auto;
  width: 4.5rem;
  height: 6rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  object-fit: cover;
}

/* -- the operator's title form (UX10-A correction 05) -- */
/*
 * Four numbered steps rather than one wall of fields. The order is the order an
 * operator works in - what it is, how it is supported, its cover, where it
 * appears - so the page can be learned by following it downwards.
 */

.titles-form {
  display: grid;
  gap: var(--gap);
}

.titles-form__step {
  margin: 0;
}

.titles-form__number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.65rem;
  height: 1.65rem;
  margin-inline-end: 0.55rem;
  border-radius: 50%;
  background: var(--accent-soft);
  border: 1px solid var(--accent-edge);
  color: var(--accent);
  font-size: 0.85rem;
  font-weight: 800;
}

/* The identifier is real and editable, and it is not what an operator came here
   for - so it is one click away rather than in the way. */
.titles-form__advanced {
  margin-block-start: 0.6rem;
}

.titles-form__advanced summary {
  cursor: pointer;
  color: var(--ink-faint);
  font-size: 0.85rem;
  font-weight: 700;
}

.titles-form__actions {
  padding-block-start: 0.2rem;
}

.btn.titles-form__remove {
  margin-inline-start: auto;
  color: var(--danger);
}

/* The cover, its picture and its controls side by side: an operator replacing a
   cover can see the one they are replacing. */
.titles-artwork {
  display: grid;
  gap: 1rem;
  align-items: start;
}

@media (min-width: 720px) {
  .titles-artwork {
    grid-template-columns: auto minmax(0, 1fr);
    gap: 1.4rem;
  }
}

.titles-artwork__preview {
  display: grid;
  justify-items: center;
  gap: 0.4rem;
  max-width: 11rem;
  text-align: center;
}

/* No cover is shown as no cover: a dashed frame, never an empty box that could
   be mistaken for a picture that failed to load. */
.titles-artwork__empty {
  display: grid;
  place-items: center;
  width: 4.5rem;
  height: 6rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  color: var(--ink-faint);
}

.titles-artwork__empty svg {
  width: 1.8rem;
  height: 1.8rem;
}

.titles-artwork__controls {
  min-width: 0;
}

/* A short list of choices as chips: all of them visible at once, one of them
   picked, and the picked one marked by more than its colour. */
.choice-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-block-start: 0.2rem;
}

.choice-chips label {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 2.5rem;
  padding: 0.3rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  color: var(--ink-soft);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}

.choice-chips label:has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, var(--surface-sunken));
  color: var(--ink);
  font-weight: 800;
}

.choice-chips label:focus-within {
  outline: 3px solid var(--focus, var(--accent));
  outline-offset: 2px;
}

/* A yes/no field reads as a question with a box, not as a heading with a stray
   box under it. */
.ops-toggle {
  display: grid;
  gap: 0.25rem;
  padding-block: 0.35rem;
}

.ops-toggle__control {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  cursor: pointer;
}

.ops-toggle__control input {
  width: 1.05rem;
  height: 1.05rem;
  margin: 0;
  flex: 0 0 auto;
}

.ops-toggle__label {
  font-weight: 700;
}

.ops-toggle .helptext {
  padding-inline-start: 1.6rem;
}

.ops-toggle--invalid .ops-toggle__label {
  color: var(--danger);
}

.titles-admin__flags {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

/* A set of checkboxes reads as a set: several to a row where there is room, one
   per row on a phone, rather than as a single tall column an operator scrolls. */
.choice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr));
  gap: 0.15rem 0.9rem;
  margin-block-start: 0.2rem;
}

/* Django wraps a checkbox group in a div, and each option in another one, so
   without this the grid would have exactly one child and lay out nothing. */
.choice-grid div,
.choice-chips div {
  display: contents;
}

.choice-grid label {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-weight: 500;
}

.choice-grid input {
  margin: 0;
}

/* --------------------------------------------------------------- footer --- */
/*
 * The footer's structure is core and identical for every brand: a brand block,
 * link columns the product actually has, then a legal strip that carries the
 * copyright, any compliance note and any trust marks.
 *
 * Every one of those last three renders only when a brand has supplied it. A
 * footer showing an empty social row or a placeholder seal would be advertising
 * something that does not exist, and a trust badge is exactly the wrong place to
 * be approximate.
 */

.site-footer {
  position: relative;
  margin-top: 3rem;
  border-top: 1px solid var(--line);
  background: var(--chrome);
  color: var(--ink-soft);
  font-size: 0.92rem;
}

.site-footer::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: -1px;
  height: 1px;
  background: var(--hairline);
}

.site-footer__inner {
  max-width: var(--shell-width);
  margin-inline: auto;
  padding: 2.75rem 1rem 1.5rem;
}

.footer-grid {
  display: grid;
  gap: 2rem;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  align-items: start;
}

.footer-brand p {
  margin: 0.9rem 0 0;
  color: var(--ink-faint);
  max-width: 30ch;
  line-height: 1.9;
}

.footer-col h2 {
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 0.85rem;
}

.footer-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.footer-col a {
  color: var(--ink-soft);
}

.footer-col a:hover {
  color: var(--accent);
}

.footer-social {
  display: flex;
  gap: 0.5rem;
  margin-top: 1rem;
  padding: 0;
  list-style: none;
}

.footer-social a {
  display: grid;
  place-items: center;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface-sunken);
  color: var(--ink-soft);
}

.footer-social a:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.footer-social svg {
  width: 1.05rem;
  height: 1.05rem;
}

.footer-legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 2.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--line);
  font-size: 0.86rem;
  color: var(--ink-faint);
}

.footer-legal p {
  margin: 0;
}

/* The trust row. Present in the layout from the start so a seal does not have to
   be retrofitted; empty, and therefore invisible, until one is configured. */
.footer-trust {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.footer-trust img {
  display: block;
  height: 3.25rem;
  width: auto;
  border-radius: var(--radius-sm);
  background: var(--surface);
  padding: 0.25rem;
  border: 1px solid var(--line);
}

/* ------------------------------------------------------------ narrow ------ */

@media (max-width: 1080px) {
  .footer-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
}

@media (max-width: 900px) {
  .hero__inner {
    padding: 5rem 1rem 3rem;
  }

  /* One column, and the identity strip takes only the height it needs. Without
     the explicit rows the shell still fills the viewport, so the two rows share
     the slack and the strip grows a band of nothing above the lockup. */
  .auth {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto 1fr;
  }

  /* A phone came here to fill in a form. What is left of the narrative half is
     an identity strip: enough to know whose front door this is, short enough
     that the first field is on the first screen. */
  /* Packed to the top, not the foot. Bottom-anchoring is what puts the words on
     the floor of the picture; with no picture there is no floor to sit on. */
  .auth__aside {
    padding: 1.5rem 1.25rem 1.35rem;
    text-align: start;
    justify-content: flex-start;
    gap: 0.6rem;
  }

  /* `display: none` and not opacity or a zero height: this is a 130 KB raster
     and the point of hiding it is that the phone never asks for it. */
  .auth__visual {
    display: none;
  }

  .auth__headline {
    font-size: 1.15rem;
    line-height: 1.55;
    max-width: none;
  }

  /* The one line that is pure atmosphere is the one a phone can do without. */
  .auth__lede {
    display: none;
  }

  /* Start the form under the identity strip instead of centring it in whatever
     is left of the screen. Centring is right when the panel is a column beside
     a picture; stacked, it just pushes the first field down past a gap. */
  .auth__panel {
    align-items: flex-start;
    border-inline-start: none;
    border-top: 1px solid var(--line);
    padding: 2.25rem 1.25rem 3rem;
  }

  /* The full navigation collapses into the disclosure. Both are always in the
     markup; which one is shown is a media query, so nothing has to be moved. */
  .site-nav,
  .header-actions {
    display: none;
  }

  /* Three columns: the menu at the logical start, the lockup in the middle, the
     controls at the logical end.

     Both side columns are `1fr`, and that is what actually centres the brand.
     Pushing it with `margin: auto` would centre it in whatever space the
     controls left over, so it would drift the moment a session badge appeared
     or a third language was added - the lockup would move because something
     unrelated to it changed. `justify-self` is logical, so this is one rule
     read from the other end in Persian and in English rather than two headers. */
  .site-header__bar {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 0.6rem;
    min-height: 3.75rem;
  }

  /* Every cell is named, row included. Without `grid-row` the lockup - which
     comes first in the markup - claims column 2 of row 1, and auto-placement
     will not go back for the menu behind it: it opens a second row instead,
     and the header quietly becomes two lines tall. */
  .nav-disclosure {
    display: block;
    grid-row: 1;
    grid-column: 1;
    justify-self: start;
  }

  .site-header__bar > .brand-lockup {
    grid-row: 1;
    grid-column: 2;
    justify-self: center;
  }

  .session-actions {
    grid-row: 1;
    grid-column: 3;
    justify-self: end;
  }

  .session-user,
  .session-actions .btn--secondary {
    display: none;
  }
}

/*
 * The auth panel on a short desktop screen.
 *
 * Registration is the tallest state this shell has, and once it really carried
 * five fields it stopped fitting: measured at 100% zoom, the foot of the panel -
 * the "back to site" link, not the button - sat at 1003px in Persian and 1024px
 * in English. A 1440x900 or 1536x864 laptop therefore had to scroll, or be
 * zoomed out, to see the whole of the product's primary form. That is the
 * problem this block exists to fix.
 *
 * The breakpoint is the measurement, not a guess: 1024px is what the tallest
 * composition needs, so every viewport below roughly that cannot fit it, and
 * 1030px is the round value just clear of it. Above this the generous rhythm is
 * kept exactly as approved, because at 1050px and 1080px the page already fits
 * and there is nothing to solve. It matters that the range reaches past 1000:
 * a maximised browser on an ordinary 1080p monitor has only ~960-1000px of
 * viewport once its own chrome is taken off, which is precisely the case that
 * was being zoomed out of.
 *
 * `min-width: 901px` keeps this to the two-column desktop layout. Below that the
 * shell is already stacked, the artwork is gone and the phone rules own the
 * spacing, so tightening it there would be solving a problem twice.
 *
 * **Whitespace only.** Nothing here changes a font size, an input height, a
 * button, a focus ring or a colour: no text is smaller, no control is smaller,
 * no help is hidden or truncated, and every one of Django's validator lines is
 * still rendered in full. The one non-margin value is the help list's
 * line-height, and it stops at 1.5 - the floor WCAG's text-spacing criterion
 * asks a page to survive - so the rules stay a readable list rather than
 * becoming a block.
 *
 * The selectors are the ones the shared field partial emits, so this applies to
 * whatever the server sends. No field is named, and adding or removing one
 * needs no change here.
 */
@media (min-width: 901px) and (max-height: 1030px) {
  /* The single largest saving, and the one that costs least: the panel centres
     its form, so on a screen where the form fits this padding is invisible and
     only the centring is seen. It becomes a real gutter exactly when the form
     is taller than the screen - which is the case being repaired. */
  .auth__panel {
    padding-block: 1.25rem;
  }

  .auth__form h1 {
    margin-bottom: 0.3rem;
  }

  .auth__form > p {
    margin-bottom: 0.85rem;
  }

  /* Between fields. Still a clear step larger than the gap inside a field, so
     the form is still read as five things rather than one block of inputs. */
  .form-stack .form-field {
    margin-bottom: 0.7rem;
  }

  .form-stack .form-field label {
    margin-bottom: 0.25rem;
  }

  .form-field__help {
    margin-top: 0.3rem;
    line-height: 1.5;
  }

  .form-stack .errorlist {
    margin-top: 0.3rem;
  }

  .form-stack .form-actions {
    margin-top: 0.9rem;
  }

  .auth__alt {
    margin-top: 0.8rem;
    padding-top: 0.8rem;
  }

  .auth__form .form-actions.spaced-above {
    margin-top: 0.9rem;
  }
}

/*
 * A second, smaller step for the screens the first one does not quite reach.
 *
 * With the block above alone, registration measures 900px in Persian and 919px
 * in English. That clears a 1000px viewport comfortably, but at 900 the English
 * page ends up exactly filling the screen - every word visible, yet with a
 * scrollbar for the last twenty pixels of gutter - and at 864 it is ~55px short.
 *
 * So the rest is taken here, below 940px, and deliberately not in the block
 * above: between 941 and 1030 - which is where a maximised browser on an
 * ordinary 1080p monitor actually lands, once its own chrome is subtracted - the
 * first step is already enough, and there is no reason to spend room that screen
 * has. The looser rhythm holds wherever it fits; only the genuinely short screen
 * pays for being short.
 *
 * Everything here is still whitespace. No font size moves, no control shrinks,
 * and the help list keeps the 1.5 line-height floor set above.
 */
@media (min-width: 901px) and (max-height: 940px) {
  .auth__panel {
    padding-block: 0.6rem;
  }

  .auth__form h1 {
    margin-bottom: 0.2rem;
  }

  .auth__form > p {
    margin-bottom: 0.55rem;
  }

  .form-stack .form-field {
    margin-bottom: 0.5rem;
  }

  .form-stack .form-field label {
    margin-bottom: 0.18rem;
  }

  .form-field__help {
    margin-top: 0.22rem;
  }

  .form-stack .form-actions {
    margin-top: 0.7rem;
  }

  .auth__alt {
    margin-top: 0.55rem;
    padding-top: 0.55rem;
  }

  .auth__form .form-actions.spaced-above {
    margin-top: 0.7rem;
  }
}

/* The rest of the session actions follow the navigation into the disclosure.

   They used to hold on until 640px, which was one breakpoint too late: between
   641 and 718 the remaining action is wider than the `1fr` column the centred
   lockup leaves it, so its label wrapped and the header grew from ~72px to
   ~93px. Measured on the running page, the last width that wraps is 660 in
   Persian and 718 in English - the English label is simply the longer string.

   The handover is here rather than at 720 because `--font` is a fallback stack
   with no @font-face: the face that actually renders "Create account" is
   whichever one the visitor's device happens to have, so the label's width is
   not a constant this stylesheet knows. Clearing the widest measured failure by
   two pixels would be a coincidence, not a margin. 768px is the tablet-portrait
   width, and it clears it by fifty.

   Nothing is taken away: the disclosure already lists sign in, create account
   and sign out, so this moves the actions rather than removing them. */
@media (max-width: 768px) {
  .session-actions .btn,
  .session-actions .inline-form {
    display: none;
  }

  /* The disclosure takes the sign-out over in the same block that takes it off
     the row, so the handover cannot half-happen and leave a customer with no
     way out - or with two. */
  .nav-disclosure__signout {
    display: block;
  }
}

/* On a phone the rail bleeds to both screen edges, so the next card is cut by
   the viewport rather than by a container - which is the whole reason a
   scroller reads as one. It keeps its own overflow, so the page itself still
   never scrolls sideways. Card width is set so a second one is always half in
   view: nobody swipes a row that looks complete. */
@media (max-width: 720px) {
  .rail {
    margin-inline: -1rem;
    padding-inline: 1rem;
    scroll-padding-inline-start: 1rem;
  }

  .rail__track {
    grid-auto-columns: 57%;
    gap: 0.7rem;
  }
}

@media (max-width: 640px) {
  .closing__inner {
    padding: 2.5rem 1.1rem;
  }

  .closing__actions .btn {
    flex: 1 1 100%;
    min-height: 2.9rem;
  }

  /* At phone width the header has to fit the lockup, the menu and the controls
     on a single row. The theme control keeps its glyph and drops its label -
     the word was never what identified it - and the language control tightens
     to the code plus its submit.

     The submit button stays. It was hidden here once, which quietly made the
     control inoperable: the <select> beside it has no change handler by
     design, so that button is the only thing that can submit the form, and
     hiding it left a language chooser that could not choose a language. Space
     is found by making it narrower, never by removing it. */
  .theme-toggle [data-theme-label] {
    display: none;
  }

  .control {
    padding-inline: 0.5rem;
  }

  .lang-switch {
    padding-inline: 0.45rem;
    gap: 0.25rem;
  }

  /* The lockup is the middle column, so every millimetre it gives back is a
     millimetre the two side columns can have before the centring gives way. */
  .site-header__bar > .brand-lockup {
    gap: 0.45rem;
  }

  .brand-lockup__name {
    font-size: 1rem;
  }

  .site-header__bar {
    gap: 0.45rem;
  }

  .brand-lockup__tagline {
    display: none;
  }

  .footer-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 1.75rem;
  }

  .footer-legal {
    flex-direction: column;
    align-items: flex-start;
  }

  .section {
    padding-block: 2.25rem;
  }

  /* A2: the fold was a screen and a half tall on a phone, so the first card
     arrived long after the scroll started. Everything below buys that back
     without cropping the composition - the globe and both characters are still
     whole, the picture is simply given less empty floor to stand on. */
  .hero {
    min-height: clamp(25rem, 68vh, 32rem);
  }

  .hero__inner {
    padding: 3rem 1.1rem 1.85rem;
  }

  .hero__copy .eyebrow {
    margin-bottom: 0.6rem;
  }

  .hero h1 {
    line-height: 1.38;
    margin-bottom: 0.6rem;
  }

  .hero__lede {
    font-size: 0.98rem;
    line-height: 1.8;
    margin-bottom: 1.15rem;
  }

  /* One column of full-width actions rather than two that wrap into an
     awkward second row of different widths. */
  .hero__actions {
    gap: 0.6rem;
  }

  .hero__actions .btn {
    flex: 1 1 100%;
    min-height: 2.9rem;
  }

  .section--lifted {
    margin-top: -1.5rem;
  }

  .section__head {
    margin-bottom: 1.15rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* SCS-P13A - public content engagement (views, Heart, Tutorial Helpful).
   Quiet and editorial: the same line, ink and accent the dateline uses. The controls start
   hidden and only the page's own script reveals them, so [hidden] must win over .btn. */
.engagement-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 1.1rem;
  padding-block: 0.6rem;
}

.engagement-meta__item {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin: 0;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.engagement-meta__item svg {
  inline-size: 1.05rem;
  block-size: 1.05rem;
  flex: none;
  color: var(--content-accent-text);
}

.engagement-meta__label {
  font-weight: 700;
}

.engagement-heart {
  margin-block-start: 2rem;
}

.engagement-heart__button {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.engagement-heart__button svg {
  inline-size: 1.1rem;
  block-size: 1.1rem;
  flex: none;
}

.engagement-heart__button[aria-pressed="true"] svg {
  fill: currentColor;
}

.engagement-heart__button[aria-pressed="true"],
.engagement-helpful__choices .btn[aria-pressed="true"] {
  border-color: currentColor;
  font-weight: 700;
}

.engagement-heart__button[hidden],
.engagement-helpful__choices[hidden],
.engagement-signin[hidden] {
  display: none;
}

.engagement-helpful {
  margin-block-start: 2rem;
  padding-block-start: 1.25rem;
  border-block-start: 1px solid var(--line);
}

.engagement-helpful__title {
  margin: 0 0 0.6rem;
  font-size: 1.1rem;
}

.engagement-helpful__choices {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-block-end: 0.6rem;
}

.engagement-helpful__rate,
.engagement-helpful__counts {
  margin: 0 0 0.3rem;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.engagement-helpful__counts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 1rem;
}

.engagement-signin {
  margin: 0.5rem 0 0;
  font-size: 0.9rem;
}

/* SCS-P13A - the Staff Content Studio row's read-only engagement summary. */
.ops-engagement {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  font-size: 0.85rem;
}

/* SCS-P13A-FIRST-03 - one generic failure message per engagement control, in a polite live
   region that stays in the accessibility tree (empty until a save fails). */
.engagement-status {
  margin: 0.4rem 0 0;
  font-size: 0.9rem;
  color: var(--danger);
}

.engagement-status:empty {
  margin: 0;
}

/* SCS-P13B - public Article comments: approved, escaped plain text under a fixed label. The
   form starts hidden; only the page's script reveals it for a visitor who may comment. */
.engagement-comments {
  margin-block-start: 2.25rem;
  padding-block-start: 1.25rem;
  border-block-start: 1px solid var(--line);
}

.engagement-comments__title {
  margin: 0 0 0.35rem;
  font-size: 1.15rem;
}

.engagement-comments__count,
.engagement-comments__empty {
  margin: 0 0 0.9rem;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.engagement-comments__list {
  display: grid;
  gap: 0.9rem;
  margin: 0 0 1rem;
  padding: 0;
  list-style: none;
}

.engagement-comment {
  padding: 0.8rem 1rem;
  border: 1px solid var(--line);
  border-radius: 0.6rem;
}

.engagement-comment__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  margin: 0 0 0.35rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.engagement-comment__author {
  font-weight: 700;
}

/* Plain text: line breaks the customer typed are kept; nothing is turned into markup. */
.engagement-comment__body,
.comment-body {
  margin: 0;
  white-space: pre-line;
  overflow-wrap: anywhere;
}

.engagement-comments__pages {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-block-end: 1.25rem;
  font-size: 0.9rem;
}

.engagement-comment-form {
  display: grid;
  gap: 0.45rem;
  max-inline-size: 42rem;
}

.engagement-comment-form[hidden] {
  display: none;
}

.engagement-comment-form textarea {
  inline-size: 100%;
  min-block-size: 6rem;
  resize: vertical;
}

.engagement-comment-form__help,
.engagement-comment-form__count {
  margin: 0;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

/* SCS-P13B-FIRST-02 - over the 2,000 code-point limit: the counter and the limit message. */
.engagement-comment-form__count[data-tone="error"],
.engagement-comment-form__limit {
  color: var(--danger);
}

.engagement-comment-form__limit {
  margin: 0;
  font-size: 0.85rem;
}

.engagement-comment-form__limit[hidden] {
  display: none;
}

.engagement-comment-form .btn {
  justify-self: start;
}

.engagement-status[data-tone="success"] {
  color: var(--ink);
}

/* SCS-P13B - the Staff comment moderation queue. */
.comment-queue {
  display: grid;
  gap: 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.comment-queue__item {
  display: grid;
  gap: 0.5rem;
  padding-block: 0.75rem;
  border-block-end: 1px solid var(--line);
}

.comment-queue__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.9rem;
  font-size: 0.85rem;
}

.comment-queue__body summary {
  cursor: pointer;
  overflow-wrap: anywhere;
}

.comment-queue__form {
  display: grid;
  gap: 0.5rem;
  max-inline-size: 40rem;
}

.comment-queue__own,
.comment-queue__confirm {
  margin: 0;
  font-size: 0.85rem;
}

/* =========================================================================
   WALLET-ADJUST-UX-01 / FINANCE-UI-DENSITY-POLISH-01 - Staff Finance, compact.

   Scoped on purpose. Every rule here is either under `.page--finance` - which
   only the Finance hub, the manual adjustment workspace and detail, and the
   adjustment policy page opt into through the staff base's `page_class` block -
   or on a `fin-` class only those pages use. No shared primitive changes size
   anywhere else in the product.
   ========================================================================= */

.page--finance .page-head {
  margin-block-end: 0.6rem;
}

.page--finance .ops-back {
  margin-block-end: 0.5rem;
}

.page--finance .card {
  padding: 0.8rem 0.95rem;
  margin-bottom: 0.8rem;
  border-radius: var(--radius);
}

.page--finance .ops-grid-2 {
  gap: 0.8rem;
  margin-bottom: 0.8rem;
}

.page--finance .badge {
  padding: 0.04rem 0.45rem;
  font-size: 0.74rem;
  line-height: 1.6;
}

/* The page's prose line-height (1.85) would otherwise set every control's height; controls
   read as one line, so they get a control's line-height. */
.page--finance .btn {
  padding: 0.42rem 0.9rem;
  font-size: 0.9rem;
  line-height: 1.4;
}

.page--finance .btn.btn--small {
  padding: 0.24rem 0.6rem;
  font-size: 0.82rem;
}

.page--finance .btn[disabled] {
  cursor: not-allowed;
  opacity: 0.55;
  box-shadow: none;
}

.page--finance .form-field {
  margin-bottom: 0.65rem;
}

.page--finance .form-field label {
  font-size: 0.86rem;
  margin-bottom: 0.2rem;
}

.page--finance .form-field input[type="text"],
.page--finance .form-field select,
.page--finance .form-field textarea {
  padding: 0.42rem 0.62rem;
  font-size: 0.92rem;
  line-height: 1.4;
}

.page--finance .form-field textarea {
  min-block-size: 3.4rem;
  resize: vertical;
}

.page--finance .form-field .helptext {
  font-size: 0.78rem;
  margin-block-start: 0.15rem;
  padding-inline-start: 0;
}

.page--finance .ops-state {
  padding-block: 0.5rem;
  margin: 0;
}

/* Tables: tighter cells on wide screens only, so the narrow stacked layout keeps
   its own spacing. */
@media (min-width: 861px) {
  .page--finance table.data.ops-table th,
  .page--finance table.data.ops-table td {
    padding: 0.42rem 0.55rem;
    font-size: 0.86rem;
  }
}

/* -- shared Finance pieces ------------------------------------------------- */

.fin-panel__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.3rem 0.75rem;
  margin-block-end: 0.55rem;
}

.fin-panel__head h2 {
  margin: 0;
  font-size: 0.98rem;
}

.fin-subhead {
  display: flex;
  align-items: center;
  margin: 0 0 0.45rem;
  font-size: 0.9rem;
}

.fin-step {
  display: inline-grid;
  place-items: center;
  inline-size: 1.25rem;
  block-size: 1.25rem;
  margin-inline-end: 0.4rem;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.72rem;
  font-weight: 800;
  flex: none;
}

.fin-notice {
  margin-block-end: 0.6rem;
  padding: 0.42rem 0.7rem;
  font-size: 0.86rem;
  line-height: 1.65;
}

.fin-note {
  margin: 0.3rem 0 0;
  color: var(--ink-faint);
  font-size: 0.8rem;
  line-height: 1.65;
}

.fin-muted {
  color: var(--ink-faint);
  font-size: 0.8rem;
  font-weight: 500;
}

.fin-block {
  display: block;
}

.fin-break {
  overflow-wrap: anywhere;
}

.fin-mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8rem;
}

.fin-error {
  margin: 0.2rem 0 0;
  color: var(--danger);
  font-size: 0.8rem;
  font-weight: 600;
}

.fin-badges {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

.fin-badge--off {
  background: transparent;
  color: var(--ink-faint);
  border-color: var(--line);
}

.fin-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
}

.fin-ref {
  font-size: 0.74rem;
}

/* Label / value facts, several to a row on wide screens. */
.fin-facts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 10.5rem), 1fr));
  gap: 0.45rem 1rem;
  margin: 0;
}

.fin-facts > div {
  min-inline-size: 0;
}

.fin-facts dt {
  color: var(--ink-faint);
  font-size: 0.74rem;
  font-weight: 700;
}

.fin-facts dd {
  margin: 0.05rem 0 0;
  font-weight: 600;
  font-size: 0.9rem;
}

.fin-facts__wide {
  grid-column: 1 / -1;
}

/* One fact per row: the detail page's ledger of a single adjustment. */
.fin-facts--rows {
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
}

.fin-facts--rows > div {
  display: grid;
  grid-template-columns: minmax(7rem, 12rem) minmax(0, 1fr);
  gap: 0.2rem 0.8rem;
  align-items: baseline;
  padding-block: 0.32rem;
  border-block-end: 1px solid var(--line);
}

.fin-facts--rows > div:last-child {
  border-block-end: 0;
}

.fin-facts--rows dd {
  margin: 0;
}

@media (max-width: 480px) {
  .fin-facts--rows > div {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* -- amounts --------------------------------------------------------------- */

.fin-amount {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.35rem;
  font-weight: 700;
}

.fin-amount__dir {
  padding: 0 0.4rem;
  border: 1px solid currentColor;
  border-radius: var(--radius-pill);
  font-size: 0.7rem;
  line-height: 1.6;
}

.fin-amount--credit .fin-amount__dir {
  color: var(--ok);
  background: var(--ok-tint);
}

.fin-amount--debit .fin-amount__dir {
  color: var(--danger);
  background: var(--danger-tint);
}

.fin-amount__irr {
  color: var(--ink-faint);
  font-size: 0.76rem;
  font-weight: 500;
}

/* -- the adjustment workspace ---------------------------------------------- */

.fin-policy-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 1.6rem;
  margin: 0;
}

.fin-policy-strip dt {
  color: var(--ink-faint);
  font-size: 0.74rem;
  font-weight: 700;
}

.fin-policy-strip dd {
  margin: 0;
  font-weight: 700;
}

.fin-policy-strip + .fin-note {
  margin-block-end: 0.7rem;
}

.fin-lookup {
  margin-block-start: 0.4rem;
}

.fin-lookup__row {
  display: flex;
  gap: 0.5rem;
  max-inline-size: 34rem;
}

.fin-lookup__row input[type="text"] {
  flex: 1 1 auto;
  min-inline-size: 0;
}

.fin-customer {
  margin-block: 0.2rem 0.8rem;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--line);
  border-inline-start: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--surface);
}

.fin-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: 0 1rem;
  align-items: start;
}

.fin-form__wide {
  grid-column: 1 / -1;
}

.fin-direction {
  min-inline-size: 0;
  margin: 0 0 0.65rem;
  padding: 0;
  border: 0;
}

.fin-direction legend {
  display: flex;
  align-items: center;
  margin-block-end: 0.2rem;
  padding: 0;
  font-size: 0.86rem;
  font-weight: 700;
}

.fin-choices {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.fin-choice {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.36rem 0.7rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.4;
  cursor: pointer;
}

.fin-choice:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.fin-choice:focus-within {
  outline: 3px solid var(--ring);
  outline-offset: 2px;
}

.fin-direction.form-field--invalid .fin-choice {
  border-color: var(--danger);
}

.fin-summary {
  margin-block: 0.15rem 0.7rem;
  padding: 0.6rem 0.8rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
}

.fin-timeline {
  margin: 0;
  padding: 0;
  list-style: none;
}

.fin-timeline > li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem 0.6rem;
  padding-block: 0.3rem;
  border-block-end: 1px solid var(--line);
  font-size: 0.84rem;
}

.fin-timeline > li:last-child {
  border-block-end: 0;
}

.fin-timeline__action {
  font-weight: 700;
}

/* -- the policy page ------------------------------------------------------- */

.fin-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 2.2rem;
  margin: 0 0 0.2rem;
}

.fin-stats dt {
  color: var(--ink-faint);
  font-size: 0.76rem;
  font-weight: 700;
}

.fin-stats dd {
  margin: 0.05rem 0 0;
}

.fin-stats__value {
  font-size: 1.12rem;
  font-weight: 800;
}

.fin-form--policy {
  /* Columns are capped, not the form: the divider above it still spans the card. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 24rem));
  margin-block-start: 0.7rem;
  padding-block-start: 0.7rem;
  border-block-start: 1px solid var(--line);
}

/* -- the Finance hub ------------------------------------------------------- */

.fin-home {
  display: grid;
  gap: 0.8rem;
  align-items: start;
}

@media (min-width: 1100px) {
  .fin-home {
    grid-template-columns: minmax(0, 1fr) minmax(17rem, 21rem);
  }
}

.fin-hub {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
  gap: 0.75rem;
  align-items: start;
}

.fin-group {
  padding: 0.6rem 0.7rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-raised);
  box-shadow: var(--shadow);
}

.fin-group__title {
  margin: 0 0 0.3rem;
  color: var(--ink-faint);
  font-size: 0.76rem;
  font-weight: 800;
}

.fin-tiles {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
}

.fin-tile {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0 0.6rem;
  align-items: center;
  padding: 0.42rem 0.5rem;
  border-radius: var(--radius-sm);
}

.fin-tile + .fin-tile {
  border-block-start: 1px solid var(--line);
}

.fin-tile:hover,
.fin-tile:focus-within {
  background: var(--accent-soft);
}

.fin-tile:has(.fin-tile__link:focus-visible) {
  outline: 3px solid var(--ring);
  outline-offset: 1px;
}

.fin-tile__link {
  grid-column: 1;
  color: var(--ink);
  font-size: 0.92rem;
  font-weight: 800;
  text-decoration: none;
}

.fin-tile__link::after {
  content: "";
  position: absolute;
  inset: 0;
}

.fin-tile__link:focus-visible {
  outline: none;
}

.fin-tile__text {
  grid-column: 1;
  margin: 0.05rem 0 0;
  color: var(--ink-soft);
  font-size: 0.8rem;
  line-height: 1.55;
}

.fin-tile__go {
  grid-column: 2;
  grid-row: 1 / span 2;
  padding: 0.1rem 0.55rem;
  border: 1px solid var(--accent);
  border-radius: var(--radius-pill);
  color: var(--accent);
  font-size: 0.74rem;
  font-weight: 700;
}

.fin-side {
  display: grid;
  gap: 0.8rem;
  align-content: start;
}

.fin-side .card {
  margin-bottom: 0;
}

.fin-caps {
  display: grid;
  margin: 0;
}

.fin-caps > div {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding-block: 0.26rem;
  border-block-end: 1px solid var(--line);
}

.fin-caps > div:last-child {
  border-block-end: 0;
}

.fin-caps dt {
  font-size: 0.84rem;
  font-weight: 600;
}

.fin-caps dd {
  margin: 0;
  flex: none;
}

.fin-details > summary {
  cursor: pointer;
  font-size: 0.88rem;
  font-weight: 700;
}

.fin-list {
  margin: 0.45rem 0 0;
  padding-inline-start: 1.1rem;
  color: var(--ink-soft);
  font-size: 0.82rem;
  line-height: 1.6;
}

.fin-list > li + li {
  margin-block-start: 0.25rem;
}

/* -- the finance report (FINANCE-REPORTING-V2-01) ------------------------------
   The management summary above the detailed movement table. Only the finance
   report renders `fin-report` classes, under `.page--finance`. */

.page--finance .fin-report__filters {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
  gap: 0 0.8rem;
}

.page--finance .fin-report__filters .form-field select {
  inline-size: 100%;
}

.fin-report__kpis {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 12rem), 1fr));
  margin-block-end: 0.4rem;
}

.fin-report__kpis dd {
  font-size: 1rem;
}

.fin-report__money {
  gap: 0 0.25rem;
}

.fin-report__breakdowns {
  margin-block-start: 0.55rem;
}

.fin-report__breakdowns .fin-subhead {
  margin-block-start: 0.65rem;
}

.fin-report__section .ops-table-wrap {
  margin-block-start: 0.45rem;
}

/* The filter panel: a <details> whose summary is the panel head and names every active
   filter, so a collapsed panel never hides what the report is narrowed to. */
.fin-report__filtersum {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.6rem;
  cursor: pointer;
  list-style: none;
}

.fin-report__filtersum::-webkit-details-marker {
  display: none;
}

.fin-report__filtersum::after {
  content: "";
  inline-size: 0.5rem;
  block-size: 0.5rem;
  margin-inline-start: auto;
  /* Physical sides on purpose: a disclosure arrow points down (closed) or up (open) in
     either direction of text. */
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  opacity: 0.7;
}

.fin-report__filterbox[open] > .fin-report__filtersum::after {
  transform: rotate(-135deg);
}

.fin-report__filtersum h2 {
  margin: 0;
  font-size: 0.98rem;
}

/* After the heading row (heading, count, chevron), on a row of their own. */
.fin-report__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  inline-size: 100%;
  order: 1;
}

.fin-report__chip {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.2rem;
  max-inline-size: 100%;
  padding: 0.05rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  font-size: 0.76rem;
  line-height: 1.6;
}

.fin-report__chip-label {
  color: var(--ink-faint);
}

.fin-report__filterbox[open] > .fin-report__filtersum {
  margin-block-end: 0.55rem;
}

.page--finance .fin-report__help {
  margin-block: 0 0.5rem;
  font-size: 0.76rem;
  line-height: 1.6;
}

/* Narrow screens: denser, two to a row where the pair belongs together (from / to,
   provider / rail, family / coupon). Identifiers and codes keep the full width. Controls
   stay at least 2.5rem tall for touch. */
@media (max-width: 640px) {
  .page--finance .fin-report__filtercard {
    padding: 0.6rem 0.75rem;
  }

  .page--finance .fin-report__filters {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 0.55rem;
  }

  .page--finance .fin-report__filters > * {
    grid-column: 1 / -1;
  }

  .page--finance .fin-report__filters > .fin-report__half {
    grid-column: auto;
  }

  .page--finance .fin-report__filters .form-field {
    margin-bottom: 0.45rem;
    min-inline-size: 0;
  }

  .page--finance .fin-report__filters .form-field label {
    margin-bottom: 0.1rem;
    font-size: 0.8rem;
    line-height: 1.5;
  }

  .page--finance .fin-report__filters .form-field input[type="text"],
  .page--finance .fin-report__filters .form-field select {
    min-block-size: 2.5rem;
    padding: 0.3rem 0.5rem;
    font-size: 0.9rem;
  }

  .page--finance .fin-report__categories {
    margin-block-end: 0.35rem;
    padding: 0.35rem 0.55rem;
  }

  .page--finance .fin-report__categories .ops-check {
    min-block-size: 2.1rem;
    margin-inline-end: 0.7rem;
    font-size: 0.84rem;
  }

  .page--finance .fin-report__kpis {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.4rem 0.7rem;
  }
}
