/*
 * public.css — the foundation under every page a CUSTOMER'S CUSTOMER sees.
 *
 * From the 2026-08-29 public-surfaces design pass (docs/design/CUSTOMER-FACING-BRIEF.md §02).
 * Seven surfaces wear a workspace's brand — /f, /b, /b/manage, /v, /r, /w, /kb — and until now
 * they shared no CSS at all: four carried their whole identity in a page-local <style>, and the
 * eight brand values lived under three different names (--pf-*, --w-*, and a bare --accent on the
 * view and report pages, which took two of the eight and invented the rest).
 *
 * ⚠️ EVERY class here is `pub-` prefixed, without exception — the same rule helpdesk.css is
 * under, and for the same reason: site.css is global, and a generic name picked here collides
 * downstream. `.field-row` is the recorded instance. Note that the view and report pages get away
 * with `.btn`, `.card` and `.wrap` today ONLY because they set `Layout = null` and site.css never
 * loads; the moment they share a file, that stops being luck.
 *
 * FOUR LAYERS, and the order is the argument:
 *   1 the brand seam    — the only place a brand value may enter
 *   2 the neutral base  — inherited from tokens.css, never redeclared
 *   3 the components    — what every public surface is built from
 *   4 the guards        — the two things a phone needs
 */

/* ── LAYER 1 · The brand seam ─────────────────────────────────────────────────
   Seven custom properties, every one from ResolvedBrand, every one injected by the page in its
   ONE permitted <style> block. Nothing in this file may be brand-carrying.

   That single sentence is what makes the file auditable: a hex in here that is not a neutral is
   a bug, and `grep -nE '#[0-9A-Fa-f]{6}' public.css` is the whole audit.

   The fallbacks are RowFold's own warm system, so an unbranded workspace looks like the product
   it is part of rather than like a third colour scheme nobody chose.

   ── THE PREFIX IS `--ws-`, AND THE JOB IS IN THE MIDDLE OF THE NAME ──────────
   These values belong to the WORKSPACE, not to whichever stylesheet happens to declare them.
   Naming them after the sheet is what produced three names for one accent (--pub-accent,
   --pf-accent and a bare --accent), and would do it again the first time a sheet is split — so
   `--pub-*` was itself the fourth instance of the bug it was written to end. Class names stay
   `pub-` prefixed, without exception: that rule is about colliding with site.css, and is
   unrelated to this one.

   `fill` and `ink` sit in the MIDDLE so that `color: var(--ws-fill-accent)` reads wrong on sight
   rather than needing a comment to explain it. Documentation could not make the mistake
   unavailable; a name can. From the 2026-08-30 public-surfaces design pass, Q2. */
:root {
    --ws-fill-accent:      var(--accent, #D9F25C);       /* FILL ONLY. Never text. */
    --ws-fill-accent-deep: var(--accent-deep, #AFD227);  /* borders, hovers. Never text. */
    --ws-fill-accent-tint: var(--accent-tint, #F2F8CF);  /* washes, bands, a selected row */
    --ws-ink-accent:       var(--accent-ink, #51631A);   /* TEXT ONLY — the only value that may be a link */
    --ws-ink-on-accent:    var(--text, #14182E);         /* ink that sits ON a fill */
    --ws-paper:            var(--paper, #FBF8F1);        /* the ground, page and email alike */
    /* A real family, not `inherit`. Every type style below is a `font:` SHORTHAND, and the
       shorthand is INVALID without a family — so `font: var(--t-title)` alone is dropped by the
       parser and sets nothing at all. That is why the type scale in this file was inert: the
       closed page's h1 measured 16px, the body default, rather than the 22px it asks for. The
       shorthands now end in var(--ws-font), and this default is what makes them parse when a
       workspace supplies no font of its own. */
    --ws-font:             var(--font-sans);
}

/* ⚠️ The defaults above are RowFold's own chartreuse, so a page's brand seam must declare ALL
   SEVEN — not merely the ones its own rules read. Whatever it omits keeps the stock value, and the
   stock value is a DIFFERENT BRAND: /kb declared five, and `.pub-btn:hover` drew a chartreuse
   border on a terracotta button, on the workspace's own public help centre. Measured Aug 30.
   A page that reads none of them still has to declare them, because the rules in THIS file do.

   ⚠️ --ws-ink-accent is fed by ResolvedBrand.AccentLinkHex, NOT by AccentDeepHex.
   AccentDeepHex is a fixed 18% shade and is not a contrast check: a pale brand stays pale, and
   the help centre shipped with every link at 1.9:1 on a chartreuse workspace before this was
   caught. AccentLinkHex darkens until it clears 4.5:1 on white. Never carry text in
   --ws-fill-accent or --ws-fill-accent-deep. */

/* ── LAYER 2 · The neutral base ───────────────────────────────────────────────
   Inherited from tokens.css and NEVER redeclared. This is the layer that pays for the file.

   Measured before it existed: /v defined its own ramp with --faint #9A9188, which is 3.1:1 on
   white and fails AA — on a public page where that colour carries the record count. /r defined a
   second, different ramp. tokens.css's greys were derived by an audit that passes on paper, card
   and rail alike, and are warm on purpose: do not "correct" them toward blue. */
.pub-sheet, .pub-shut {
    color: var(--text);
    font-family: var(--ws-font);
}

/* ── LAYER 3 · The components ─────────────────────────────────────────────────
   Every public surface is built from these. Six existed somewhere already — the work is naming
   them once instead of four times. Only .pub-shut is new, and it is new because nobody had
   drawn the closed page. */

/* 1 · The page and its column. */
.pub-body { margin: 0; background: var(--ws-paper); color: var(--text); font: var(--t-body) var(--ws-font); }
.pub-wrap { max-width: 760px; margin: 0 auto; padding: var(--s-7) var(--s-4) var(--s-8); }
.pub-wrap.is-wide { max-width: 1180px; }

/* 2 · The sheet — the white card a public page's content sits on. */
.pub-sheet {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--r-card);
    padding: var(--s-5);
}

/* 3 · The brand header — logo, or the organisation's name when there is no logo.
       Never both: a wordmark beside the same word reads as a mistake. */
.pub-brand { display: flex; align-items: flex-start; gap: var(--s-3); margin-bottom: var(--s-5); flex-wrap: wrap; }
.pub-logo { max-height: 34px; width: auto; display: block; border-radius: var(--r-chip); }
.pub-org {
    font: var(--t-micro) var(--ws-font); letter-spacing: var(--t-micro-track);
    text-transform: uppercase; color: var(--text-faint); margin: 0;
}
.pub-title { font: var(--t-display) var(--ws-font); letter-spacing: var(--t-display-track); margin: 0 0 var(--s-2); }
.pub-lede { font: var(--t-subhead) var(--ws-font); color: var(--text-2); margin: 0; text-wrap: pretty; }

/* 4 · Buttons. Two weights and no more: the thing you came to do, and everything else. */
.pub-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
    font: var(--t-body) var(--ws-font); font-weight: 600;
    padding: 11px var(--s-4); border-radius: var(--r-ctl);
    border: 1px solid var(--border); background: var(--card); color: var(--text);
    text-decoration: none; cursor: pointer;
}
.pub-btn:hover { border-color: var(--ws-fill-accent-deep); }
.pub-btn.is-primary { background: var(--ws-fill-accent); color: var(--ws-ink-on-accent); border-color: transparent; }
.pub-btn:disabled { opacity: .5; cursor: default; }
.pub-btn:focus-visible { outline: 2px solid var(--ws-ink-accent); outline-offset: 2px; }

/* 5 · Fields. */
.pub-field { margin-bottom: var(--s-4); }
.pub-label { display: block; font: var(--t-label) var(--ws-font); color: var(--text); margin-bottom: var(--s-2); }
.pub-input {
    width: 100%; font: var(--t-body) var(--ws-font); padding: 11px var(--s-3);
    border: 1px solid var(--border-2); border-radius: var(--r-ctl);
    background: var(--card); color: var(--text);
}
.pub-input:focus { outline: 2px solid var(--ws-ink-accent); outline-offset: 1px; border-color: transparent; }
.pub-help { font: var(--t-hint) var(--ws-font); color: var(--text-faint); margin: var(--s-2) 0 0; }

/* 6 · A table that scrolls in its OWN box. The page body must never scroll sideways — the
       standing rule for wide content everywhere in this product. */
.pub-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.pub-table { border-collapse: collapse; width: 100%; font: var(--t-body) var(--ws-font); }
.pub-table th, .pub-table td {
    padding: 9px var(--s-3); border-bottom: 1px solid var(--border);
    text-align: left; white-space: nowrap;
}
.pub-table th {
    font: var(--t-micro) var(--ws-font); letter-spacing: var(--t-micro-track);
    text-transform: uppercase; color: var(--text-faint);
}
.pub-table tr:last-child td { border-bottom: 0; }

/* 7 · The closed page. NEW — nobody had drawn it, and six surfaces each wrote their own wording.
       It is the most-seen state after the happy path.

       ⚠️ It must stay UNIFORM WITHIN A SURFACE: unknown token, expired, disabled, revoked and
       dormant-workspace all render identically, because a distinguishable "expired" confirms to a
       stranger that the token was once real. It is deliberately unbranded — a closed page cannot
       know whose brand to wear without leaking exactly the fact it is refusing to confirm.

       Two thirds house, one third slot: the noun and the middle sentence are fixed for all nine
       and live in Services/PublicClosedCopy.cs; the TAIL is the only line a surface writes. The
       two paragraphs are deliberately different weights — the middle one is the refusal, the tail
       is what to do about it, and a reader who only takes one should take the second. */
.pub-shut {
    min-height: 100vh; display: flex; align-items: center; justify-content: center;
    background: var(--paper); padding: var(--s-5); text-align: center;
}
.pub-shut-inner { max-width: 34ch; }
.pub-shut h1 { font: var(--t-title) var(--ws-font); margin: 0 0 var(--s-2); }
.pub-shut p { font: var(--t-body) var(--ws-font); color: var(--text-muted); margin: 0 0 var(--s-3); text-wrap: pretty; }
/* Qualified, not bare: `.pub-shut p` above is (0,1,1) and would beat a lone `.pub-shut-tail`
   (0,1,0), so the tail silently kept the middle sentence's colour. */
.pub-shut p.pub-shut-tail { color: var(--text-faint); margin-bottom: 0; }
.pub-shut .pub-shut-action { margin-top: var(--s-4); }

/* The chat, which renders in an iframe on somebody else's site and may be 320px wide. Not a
   phone breakpoint: the frame is narrow at every viewport, so this is keyed to the surface. */
.pub-shut.is-compact { min-height: 0; padding: var(--s-4); }
.pub-shut.is-compact .pub-shut-inner { max-width: 30ch; }
.pub-shut.is-compact h1 { font: var(--t-subhead) var(--ws-font); }
.pub-shut.is-compact p { font: var(--t-hint) var(--ws-font); }

/* A label a screen reader needs and the design does not draw — a search box whose placeholder is
   its only description is unlabelled to anything that does not render placeholders. `pub-`
   prefixed like everything else here: site.css ships a global `.sr-only`, and these pages set
   Layout = null precisely so it never loads. */
.pub-sr-only {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* The footer badge, shown only when the brand says so. */
.pub-badge { font: var(--t-hint) var(--ws-font); color: var(--text-faint); margin-top: var(--s-6); }
.pub-badge a { color: var(--text-faint); }

/* Links carry the contrast-checked value, never the raw accent. */
.pub-body a, .pub-sheet a { color: var(--ws-ink-accent); }

/* ── LAYER 4 · The guards ─────────────────────────────────────────────────────
   Two media blocks, both about a phone, which is how these pages are overwhelmingly opened.

   They were written out identically in publicform.css and booking.css and were ABSENT from the
   view, report, help centre and rating pages — which is where a stranger reads a table on a
   phone. That gap is the whole argument for a file rather than a stated pattern: a pattern
   cannot be absent by accident, it can only be un-followed, quietly, by whoever writes the next
   page. It was un-followed four times. */

/* 1 · iOS ZOOMS THE PAGE when a control under 16px takes focus, and does not zoom back out. A
       13px input turns a one-tap task into a pinch-and-scroll one. */
@media (max-width: 820px) {
    .pub-body input, .pub-body textarea, .pub-body select, .pub-body button { font-size: 16px; }
}

/* 2 · 44px is the smallest target a finger hits reliably. */
@media (pointer: coarse) {
    .pub-body .pub-btn,
    .pub-body .pub-input,
    .pub-body button,
    .pub-body [role="button"] { min-height: 44px; }
}

@media (max-width: 520px) {
    .pub-wrap { padding: var(--s-6) var(--s-4) var(--s-7); }
    .pub-sheet { padding: var(--s-4); }
}

@media (prefers-reduced-motion: reduce) {
    .pub-body *, .pub-body *::before, .pub-body *::after {
        animation-duration: 0.01ms !important; transition-duration: 0.01ms !important;
    }
}
