/* =========================================================================
   CourtScheduler — the PUBLIC site (PB-02)
   =========================================================================

   WHY THIS IS A SEPARATE FILE.

   §23 asks that the public site not regress the frozen internal UI, and the
   only way to promise that structurally is for the public rules to live
   somewhere the internal pages never load. court-scheduler.css is served to
   every internal screen; a public rule added to it would be one careless
   selector away from restyling a screen it was never meant to touch. This
   file is served only by _LayoutPublic.cshtml, so an error in it cannot reach
   the staff application at all.

   SCOPING, TWICE OVER. Every rule below is nested under `.cs-public`, which
   appears on exactly one element in the application: the <body> of the public
   layout. There is no `body`, `.btn`, `.card` or `table` rule here, and no
   `:root` block — §23 names those specifically, and they are the selectors
   that leak.

   THE TOKENS ARE COPIED, AND A TEST KEEPS THE COPY HONEST.

   The first draft of this file borrowed the palette by loading
   court-scheduler.css alongside it, which is what _LoginLayout does. Measured,
   that was the wrong trade for a public page: 113KB of internal component CSS
   served to a first-time visitor on a phone, of which this page uses the
   twenty-odd custom properties below — and its comments and class taxonomy
   describe the staff application's screens some fifty times over, published to
   the internet as page source. §21 rules out the weight and §2 rules out the
   vocabulary.

   WHICH IS WHY THIS FILE'S OWN COMMENTS NAME NO INTERNAL SCREEN. A CSS comment
   is served. Rationale that has to name one belongs in the design document,
   not in a file a stranger can read; a test asserts it stays that way.

   So the tokens this page uses are declared here, VERBATIM from the values
   UI-10B sampled out of the Crisron artwork. A second copy of a palette is
   normally a second thing to drift — which is why Pb02PublicLandingTests parses
   both files and requires every value below to be byte-identical to
   court-scheduler.css's. Change the brand there and this file fails until it
   agrees. §13's "use the identity that already exists" is then enforced rather
   than intended.

   `.cs-scope` is deliberately NOT on the public <body>. Every rule in
   court-scheduler.css is nested under it, so its absence means the internal
   stylesheet could not style this page even if some future layout loaded it.

   ========================================================================= */

.cs-public {
    /* ---------------------------------------------------------------------
       THE BRAND LAYER — copied from court-scheduler.css, test-enforced.

       UI-10B decoded wwwroot/images/crisron-logo.png pixel by pixel and these
       are the modal colours of the regions they name: navy #293c88 for the
       paddle and the PICKLEBALL wordmark, gold #f6ca33 for the ball, amber
       #f5ac22 across the swoosh. They are not estimates and must not be
       re-eyeballed.
       --------------------------------------------------------------------- */
    --cs-brand-primary: #293c88;
    --cs-brand-primary-hover: #1f2e69;
    --cs-brand-primary-soft: #eef0f7;
    --cs-brand-accent: #f6ca33;
    --cs-brand-accent-amber: #f5ac22;

    /* The wordmark's navy taken down to near-black: the page reads as navy
       rather than as grey, at 16:1 on white. */
    --cs-brand-ink: #18203c;
    --cs-brand-ink-muted: #565f75;

    /* PB-03 additions, same rule as the block above: copied verbatim, parity
       enforced by test. */
    --cs-brand-secondary-ink: #a4113a;
    --cs-brand-secondary-soft: #fdecef;
    --cs-success: #1c6b3f;

    /* --- surface ------------------------------------------------------- */
    --cs-bg: #f5f7fa;
    --cs-surface: #ffffff;
    --cs-surface-muted: #eef1f6;
    --cs-border: #dde2ec;
    --cs-border-strong: #b8c0d4;

    /* PB-04B. THE BOUNDARY OF AN INTERACTIVE CONTROL, and it is a different requirement
       from the boundary of a box.

       --csp-, NOT --cs-. The public stylesheet repeats the brand palette from
       court-scheduler.css and a PB-02 control requires every --cs-* here to exist there with a
       byte-identical value, so that re-theming the venue in one place fails until the other
       agrees. This token is public-only - there is no provider button in the staff application -
       so it takes the --csp- prefix reserved for exactly that. The first version of this change
       used --cs- and the control caught it on the full suite.

       WCAG 2.1 SC 1.4.11 asks for 3:1 on the visual information needed to identify a user
       interface component. The provider button is a white surface on a white page, so its
       BORDER is the only thing that says a control is there - and --cs-border-strong is
       1.82:1 against white, measured in the browser during the PB-04B walkthrough. This
       token is 3.68:1. */
    --csp-border-control: #7885a6;

    /* --- text ---------------------------------------------------------- */
    --cs-text: var(--cs-brand-ink);
    --cs-text-muted: var(--cs-brand-ink-muted);
    --cs-text-inverse: #ffffff;

    /* --- spacing ------------------------------------------------------- */
    --cs-space-xs: 4px;
    --cs-space-sm: 8px;
    --cs-space-md: 12px;
    --cs-space-lg: 16px;
    --cs-space-xl: 24px;

    /* --- radius -------------------------------------------------------- */
    --cs-radius-sm: 4px;
    --cs-radius-md: 6px;
    --cs-radius-lg: 10px;

    /* --- typography ---------------------------------------------------- */
    --cs-font-xs: 12px;
    --cs-font-sm: 13px;
    --cs-font-base: 14px;
    --cs-font-md: 16px;

    /* --- interaction ---------------------------------------------------
       44px is roughly the contact patch of an adult fingertip. §19 asks for it
       on mobile; it is the floor everywhere here. */
    --cs-touch-target: 44px;
    --cs-focus-color: rgba(41, 60, 136, .9);

    /* --- layers -------------------------------------------------------- */
    --cs-layer-nav: 1000;
    --cs-layer-toast: 1100;

    /* ---------------------------------------------------------------------
       THE PUBLIC SITE'S OWN MEASUREMENTS — spacing and type only.

       A marketing page is read at a different distance from an operations
       board. The internal type scale tops out at 24px because a dense grid
       cannot afford more; a hero headline needs to be the first thing seen
       from across a phone. These carry the --csp- prefix so they can never be
       confused with a token the internal stylesheet also defines.
       --------------------------------------------------------------------- */
    --csp-max: 1120px;
    --csp-gutter: 24px;

    --csp-display: 44px;
    --csp-h2: 28px;
    --csp-lede: 18px;
    --csp-body: 16px;

    /* The section rhythm. One value, so the page has a beat rather than six
       independent paddings that nearly agree. */
    --csp-band: 72px;

    background: var(--cs-surface);
    color: var(--cs-text);
    font-size: var(--csp-body);
    line-height: 1.55;

    /* §19. NO DOCUMENT-LEVEL HORIZONTAL OVERFLOW, DECLARED RATHER THAN HOPED.
       The hero's decorative wash is positioned, and a positioned element that
       overshoots by a pixel gives a phone a sideways scroll on a page with
       nothing to scroll to. */
    overflow-x: hidden;
}

/* =========================================================================
   Skip link (§20)
   =========================================================================

   The first focusable thing on the page, visible only when focused. Without
   it a keyboard visitor tabs through the header on every section jump — which
   on a page this short is a small cost, and is still the wrong default.       */

.cs-public .cs-public__skip {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: var(--cs-layer-toast);
    padding: 12px 20px;
    background: var(--cs-brand-primary);
    color: var(--cs-text-inverse);
    font-weight: 700;
    text-decoration: none;
    border-radius: 0 0 var(--cs-radius-md) 0;
}

.cs-public .cs-public__skip:focus {
    left: 0;
}

/* =========================================================================
   Shared layout primitives
   ========================================================================= */

.cs-public .cs-public__wrap {
    width: 100%;
    max-width: var(--csp-max);
    margin: 0 auto;
    padding: 0 var(--csp-gutter);
}

/* =========================================================================
   Header (§17)
   ========================================================================= */

.cs-public .cs-public__header {
    background: var(--cs-surface);
    border-bottom: 1px solid var(--cs-border);
    position: sticky;
    top: 0;
    z-index: var(--cs-layer-nav);
}

.cs-public .cs-public__bar {
    width: 100%;
    max-width: var(--csp-max);
    margin: 0 auto;
    padding: 12px var(--csp-gutter);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cs-space-lg);

    /* §19. The header must survive 390px with a two-item nav; wrapping is the
       graceful failure, a squeezed brand is not. */
    flex-wrap: wrap;
}

.cs-public .cs-public__brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    color: inherit;

    /* §19. A touch target, not just a logo. */
    min-height: var(--cs-touch-target);
}

.cs-public .cs-public__brand-logo {
    width: 40px;
    height: 40px;

    /* §16. Both dimensions declared so the row does not reflow when the image
       arrives — a logo that resizes the header on load is the cheapest
       possible layout shift and the easiest to prevent. */
    object-fit: contain;
    flex: 0 0 auto;
}

.cs-public .cs-public__brand-text {
    display: flex;
    flex-direction: column;
    line-height: 1.15;
}

.cs-public .cs-public__brand-name {
    font-size: 18px;
    font-weight: 800;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--cs-brand-primary);
}

.cs-public .cs-public__brand-sub {
    font-size: var(--cs-font-xs);
    font-weight: 600;
    letter-spacing: .10em;
    text-transform: uppercase;
    color: var(--cs-text-muted);
}

.cs-public .cs-public__nav {
    display: flex;
    align-items: center;
    gap: var(--cs-space-md);
}

.cs-public .cs-public__nav-link {
    display: inline-flex;
    align-items: center;
    min-height: var(--cs-touch-target);
    padding: 0 12px;
    border-radius: var(--cs-radius-md);
    font-size: var(--cs-font-base);
    font-weight: 700;
    color: var(--cs-text);
    text-decoration: none;
}

.cs-public .cs-public__nav-link:hover {
    color: var(--cs-brand-primary);
    background: var(--cs-brand-primary-soft);
}

/* =========================================================================
   The primary call to action (§8, §14)
   ========================================================================= */

.cs-public .cs-public__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;

    /* §19. 48px, above the 44px floor, because this is the one control the
       whole page exists to get pressed. */
    min-height: 48px;
    padding: 0 28px;

    border: 0;
    border-radius: 999px;
    background: var(--cs-brand-accent);

    /* NAVY ON GOLD, NEVER GOLD ON WHITE. The brand gold is about 1.8:1 on
       white and unreadable as text; the brand navy on top of it measures
       6.40:1, and 5.16:1 against the amber this button hovers to. Both clear
       AA for the 18px text used here with room to spare.

       UI-10B's "about 9:1" figure is for --cs-brand-ink on gold (10.23:1
       measured), which is a DIFFERENT pairing — the near-black body colour,
       not the brand blue. The blue is used here because it is the logo's own
       navy-paddle-on-gold-ball relationship. Recorded because a comment
       claiming a margin the colours do not have is how a later darkening of
       the gold gets waved through. */
    color: var(--cs-brand-primary);

    font-size: var(--csp-lede);
    font-weight: 800;
    letter-spacing: .01em;
    text-decoration: none;
    box-shadow: 0 6px 18px rgba(41, 60, 136, .18);
}

.cs-public .cs-public__cta:hover {
    background: var(--cs-brand-accent-amber);
}

.cs-public .cs-public__cta--sm {
    min-height: var(--cs-touch-target);
    padding: 0 18px;
    font-size: var(--cs-font-base);
    box-shadow: none;
}

/* §20. ONE VISIBLE FOCUS RULE FOR EVERY INTERACTIVE ELEMENT ON THE PAGE.
   Written once, so a control added later cannot be the one that forgot. */
.cs-public a:focus-visible {
    outline: 3px solid var(--cs-focus-color);
    outline-offset: 3px;
    border-radius: var(--cs-radius-sm);
}

/* =========================================================================
   Hero (§14, §15)
   =========================================================================

   The layout treatment that stands in for photography. The navy the wordmark
   is set in, with the swoosh's gold and amber laid over it as two soft radial
   washes — the logo's own gradient, at page scale.                            */

.cs-public .cs-public__hero {
    position: relative;
    overflow: hidden;
    background: var(--cs-brand-primary);
    color: var(--cs-text-inverse);
    padding: calc(var(--csp-band) + 16px) 0 var(--csp-band);
}

.cs-public .cs-public__hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(60% 90% at 88% 8%, rgba(246, 202, 51, .30), transparent 62%),
        radial-gradient(55% 80% at 8% 100%, rgba(239, 131, 20, .26), transparent 60%);
    pointer-events: none;
}

.cs-public .cs-public__hero-inner {
    position: relative;
    width: 100%;
    max-width: var(--csp-max);
    margin: 0 auto;
    padding: 0 var(--csp-gutter);
}

.cs-public .cs-public__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 var(--cs-space-lg);
    padding: 6px 14px 6px 12px;
    border: 1px solid rgba(255, 255, 255, .28);
    border-radius: 999px;
    background: rgba(255, 255, 255, .08);
    font-size: var(--cs-font-xs);
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
}

.cs-public .cs-public__eyebrow-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--cs-brand-accent);
    flex: 0 0 auto;
}

.cs-public .cs-public__headline {
    margin: 0 0 var(--cs-space-lg);
    font-size: var(--csp-display);
    font-weight: 800;
    line-height: 1.12;
    letter-spacing: -.01em;

    /* WIDE ENOUGH FOR THE LINE THE MARKUP ALREADY BREAKS.
     *
     * 18ch measured 459px at the display size, which is narrower than the
     * second sentence: the headline's own <br /> was overruled and "Then just
     * turn up and play." wrapped again, so the first thing on the page read as
     * three ragged lines instead of two deliberate ones. 28ch clears the
     * longest line and still stops the headline running the full 1120px on a
     * wide monitor, where a display-size line that long stops scanning. */
    max-width: 28ch;
}

.cs-public .cs-public__lede {
    margin: 0 0 var(--cs-space-xl);
    font-size: var(--csp-lede);
    line-height: 1.55;

    /* WHITE AT 88%, NOT A GREY. On the brand navy this measures about 12:1;
       a --cs-text-muted grey would land near 2:1 and disappear. */
    color: rgba(255, 255, 255, .88);
    max-width: 56ch;
}

.cs-public .cs-public__actions {
    margin: 0 0 var(--cs-space-md);
}

.cs-public .cs-public__note {
    margin: 0;
    font-size: var(--cs-font-base);

    /* §20. NOT CONVEYED BY COLOUR. This says what it means in words; the
       lighter tone is emphasis, not the message. */
    color: rgba(255, 255, 255, .78);
}

/* =========================================================================
   Sections
   ========================================================================= */

.cs-public .cs-public__section {
    padding: var(--csp-band) 0;
}

.cs-public .cs-public__section--muted {
    background: var(--cs-bg);
    border-top: 1px solid var(--cs-border);
    border-bottom: 1px solid var(--cs-border);
}

.cs-public .cs-public__title {
    margin: 0 0 var(--cs-space-sm);
    font-size: var(--csp-h2);
    font-weight: 800;
    line-height: 1.2;
    color: var(--cs-brand-ink);
}

.cs-public .cs-public__sub {
    margin: 0 0 var(--cs-space-xl);
    font-size: var(--csp-body);
    color: var(--cs-text-muted);
}

.cs-public .cs-public__body {
    margin: 0 0 var(--cs-space-md);
    max-width: 68ch;
    color: var(--cs-text);
}

/* =========================================================================
   The four steps (§9)
   ========================================================================= */

.cs-public .cs-public__steps {
    /* The numerals are drawn by the counter below, so the browser's own list
       markers are turned off — the semantics of <ol> are kept, the default
       presentation is not. */
    list-style: none;
    counter-reset: csp-step;
    margin: 0;
    padding: 0;

    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--cs-space-lg);
}

.cs-public .cs-public__step {
    counter-increment: csp-step;
    position: relative;
    background: var(--cs-surface);
    border: 1px solid var(--cs-border);
    border-radius: var(--cs-radius-lg);
    padding: 56px var(--cs-space-lg) var(--cs-space-lg);
}

.cs-public .cs-public__step::before {
    content: counter(csp-step);
    position: absolute;
    top: var(--cs-space-lg);
    left: var(--cs-space-lg);
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--cs-brand-primary);
    color: var(--cs-text-inverse);
    font-size: var(--cs-font-sm);
    font-weight: 800;
}

.cs-public .cs-public__step-title {
    margin: 0 0 var(--cs-space-xs);
    font-size: var(--cs-font-md);
    font-weight: 700;
    color: var(--cs-brand-ink);
}

.cs-public .cs-public__step-text {
    margin: 0;
    font-size: var(--cs-font-base);
    color: var(--cs-text-muted);
}

/* =========================================================================
   Footer (§18)
   ========================================================================= */

.cs-public .cs-public__footer {
    background: var(--cs-brand-ink);
    color: var(--cs-text-inverse);
    padding: 40px 0;
}

.cs-public .cs-public__footer-inner {
    display: grid;
    grid-template-columns: 2fr 1fr 1.4fr;
    gap: var(--cs-space-xl);
    align-items: start;
}

.cs-public .cs-public__footer-brand {
    margin: 0;
    font-size: var(--cs-font-md);
    font-weight: 800;
    letter-spacing: .04em;
}

.cs-public .cs-public__footer-block {
    display: grid;
    gap: 2px;
    align-content: start;
}

.cs-public .cs-public__footer-address {
    margin: 0;
    font-style: normal;
    font-size: var(--cs-font-base);
    line-height: 1.5;
    color: rgba(255, 255, 255, .78);
}

.cs-public .cs-public__footer-label {
    margin: 0 0 2px;
    font-size: var(--cs-font-xs);
    font-weight: 800;
    letter-spacing: .10em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .62);
}

.cs-public .cs-public__footer-value {
    margin: 0;
    font-size: var(--cs-font-base);
    color: rgba(255, 255, 255, .88);
}

/* Underlined, not colour-only: the footer ground is dark and a tinted link
   on it is exactly the "meaning carried by colour alone" §18 rules out. */
.cs-public .cs-public__footer-link {
    color: #ffffff;
    text-decoration: underline;
    text-underline-offset: 2px;

    /* Same reasoning as .cs-public__link - the footer repeats both actions.
       14px rather than 13px because the footer sets these one step smaller,
       and 13 left them a pixel under the floor. Measured, not assumed. */
    padding: 14px 0;
}


/* =========================================================================
   PB-02C — the photographic hero (§4)
   =========================================================================

   The plain hero above stays exactly as it was and is still what renders
   when no photograph has been supplied. This class is added on top of it
   only when the file exists, so the two are one component in two states
   rather than two heroes to keep in step.                                   */

.cs-public .cs-public__hero--photo {
    /* The photograph, behind the scrim, behind the words. The image itself
       is set inline from the view because only the server knows whether the
       file is there; everything about HOW it is presented lives here. */
    background-image: var(--csp-hero-image);
    background-size: cover;

    /* THE CROP IS ANCHORED TO THE CENTRE-BOTTOM, NOT THE MIDDLE.
     *
     * A hall photographed from standing height puts the court surface in the
     * lower two thirds and roof trusses in the upper third. Cover-cropping
     * from the centre on a wide, short viewport throws away the courts and
     * keeps the ceiling — a picture of a warehouse roof above the words
     * "Book your court". Biasing downward keeps the playing surface in frame
     * at every aspect ratio §17 asks for. */
    background-position: center 65%;
    background-repeat: no-repeat;
}

/* THE SCRIM. NOT DECORATION — IT IS WHAT KEEPS THE TEXT LEGIBLE.
 *
 * A lit indoor court is bright, busy and pale in exactly the band the
 * headline occupies, and white type laid straight onto it would fail
 * contrast outright — and would fail differently for every photograph
 * swapped in, which is worse, because it would pass review on the frame it
 * was designed against.
 *
 * THE STOPS ARE MEASURED, NOT EYEballed. The first draft ran .96 -> .90 ->
 * .62 -> .48 across the width, which looked right and was not: computed
 * against the worst backdrop these photographs actually contain — the LED
 * fittings and pale roof, around #ebeef0 — the lede fell to 2.76:1 and the
 * status note to 2.50:1, both far below AA. The falloff now stays at or
 * above .86 through 60% of the width, which is past the right edge of the
 * widest text element on the hero (the lede, capped at 56ch), and only
 * thins beyond it where nothing is set. Worst case over that same ceiling
 * is then about 7:1.
 *
 * So the rule for changing these numbers: text may only sit where the scrim
 * is >= .86. Widen the text and the stops move with it.
 *
 * It reuses the brand navy rather than plain black: a black scrim over a
 * blue-and-green court reads as a dimmed photo, a navy one reads as the
 * page. */
.cs-public .cs-public__hero--photo::before {
    background:
        linear-gradient(100deg,
            rgba(31, 46, 105, .97) 0%,
            rgba(31, 46, 105, .94) 46%,
            rgba(31, 46, 105, .86) 60%,
            rgba(31, 46, 105, .42) 100%),
        radial-gradient(58% 85% at 88% 6%, rgba(246, 202, 51, .20), transparent 60%);
}

/* =========================================================================
   PB-02C — venue information (§5)
   ========================================================================= */

.cs-public .cs-public__venue {
    display: grid;
    grid-template-columns: minmax(280px, 3fr) 4fr;
    gap: var(--cs-space-xl);
    align-items: start;
}

/* A description list, because that is what a label/value pair is. The rows
   are laid out here; the <dl>/<dt>/<dd> semantics are left intact so the
   pairing survives without styles. */
.cs-public .cs-public__facts {
    margin: 0;
    display: grid;

    /* Wider than the other stacks: the contact rows carry inline padding for
       their touch targets, which paints outside the line box and would
       otherwise sit on top of the label beneath it. */
    gap: var(--cs-space-xl);
}

.cs-public .cs-public__fact {
    display: grid;
    gap: 2px;
}

.cs-public .cs-public__fact-label {
    font-size: var(--cs-font-xs);
    font-weight: 800;
    letter-spacing: .10em;
    text-transform: uppercase;
    color: var(--cs-text-muted);
}

.cs-public .cs-public__fact-value {
    margin: 0;
    font-size: var(--csp-body);
    color: var(--cs-text);
}

.cs-public .cs-public__address {
    font-style: normal;
    line-height: 1.5;
}

.cs-public .cs-public__link {
    color: var(--cs-brand-primary);
    font-weight: 700;
    text-decoration: underline;
    text-underline-offset: 2px;

    /* THE TOUCH TARGET, WITHOUT BREAKING THE WRAP.
     *
     * These two links dial a phone and open a mail client - on a handset they
     * are the most-tapped things on the page, and they measured 19px tall.
     *
     * The obvious fixes both cost something: inline-flex or inline-block would
     * reach 44px but stop the address wrapping, and a 34-character email in a
     * 390px column then pushes the document sideways. Vertical padding on an
     * INLINE element grows the painted and hit box without touching line
     * breaking, so the target reaches the floor and the email still wraps. The
     * padding does not add to line height, which is why the rows below are
     * spaced by their own container rather than by this. */
    padding: 13px 0;
}

/* A long email address must break rather than push the column wider than
   the screen — §17 names it, and it is the single likeliest source of
   horizontal overflow on a 390px page. */
.cs-public .cs-public__link--wrap {
    overflow-wrap: anywhere;
}

.cs-public .cs-public__link:hover {
    color: var(--cs-brand-primary-hover);
}

/* The map action is a real target, not a text link: it is the one thing on
   this section somebody taps while standing up. */
.cs-public .cs-public__maplink {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: var(--cs-touch-target);
    padding: 0 16px;
    border: 1px solid var(--cs-brand-primary);
    border-radius: 999px;
    color: var(--cs-brand-primary);
    font-weight: 700;
    text-decoration: none;
}

.cs-public .cs-public__maplink:hover {
    background: var(--cs-brand-primary);
    color: var(--cs-text-inverse);
}

.cs-public .cs-public__ext {
    font-size: 14px;
    line-height: 1;
}

/* Available to a screen reader, absent from the visual layout. Used to say
   that the map opens in a new tab, which sighted users learn from the arrow
   glyph beside it. */
.cs-public .cs-public__sr {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* =========================================================================
   PB-02C — venue photography (§3, §16)
   ========================================================================= */

.cs-public .cs-public__gallery {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--cs-space-md);
}

.cs-public .cs-public__photo {
    display: block;
    width: 100%;
    height: 100%;

    /* ASPECT-RATIO PLUS OBJECT-FIT, NOT A FIXED HEIGHT.
     *
     * §3 forbids stretching. The intrinsic width/height on the <img> reserve
     * the box before the file arrives so nothing reflows; the ratio here
     * makes the tiles agree with each other; and object-fit: cover crops the
     * overflow instead of distorting it. A fixed height with no object-fit
     * is exactly how photographs get squashed. */
    aspect-ratio: 3 / 2;
    object-fit: cover;

    border-radius: var(--cs-radius-lg);
    background: var(--cs-surface-muted);
}

/* The first frame spans the row: a strip of three equal tiles reads as a
   contact sheet, one lead image with two supporting reads as a venue. */
.cs-public .cs-public__photo:first-child {
    grid-column: 1 / -1;
    aspect-ratio: 16 / 9;
}

/* =========================================================================
   PB-02C — court rules (§7, §18)
   ========================================================================= */

.cs-public .cs-public__rules {
    list-style: none;
    margin: 0;
    padding: 0;

    /* Two columns of short statements at desktop width; fourteen rules in a
       single 68ch column is a wall nobody finishes. */
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--cs-space-sm) var(--cs-space-xl);
}

.cs-public .cs-public__rule {
    position: relative;
    padding-left: 26px;
    font-size: var(--cs-font-md);
    line-height: 1.5;
    color: var(--cs-text);
}

/* THE TICK IS DECORATION AND SAYS SO.
 *
 * Generated content, so it is not in the accessibility tree and a screen
 * reader hears fourteen rules rather than fourteen check marks. §18: the
 * meaning is carried by the sentence, never by the mark beside it. */
.cs-public .cs-public__rule::before {
    content: "";
    position: absolute;
    left: 4px;
    top: .55em;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--cs-brand-accent);
}

/* =========================================================================
   Responsive (§19, §32)
   =========================================================================

   Verified at 1440, 1280, 1024, 768, 600 and 390. The breakpoints below are
   where the CONTENT stops fitting, not where a device catalogue says a class
   of device begins: the four steps stop reading as steps around 900px, and the
   hero display size stops fitting a headline around 700px.                    */

@media (max-width: 900px) {
    .cs-public .cs-public__steps {
        grid-template-columns: repeat(2, 1fr);
    }

    /* PB-02C. The facts stop sitting beside the photographs well before the
       photographs stop being useful: at 900px the fact column is squeezed to
       about 280px and the postal address starts wrapping mid-line. Stacked,
       both get full width. */
    .cs-public .cs-public__venue {
        grid-template-columns: 1fr;
    }

    .cs-public .cs-public__footer-inner {
        grid-template-columns: 1fr 1fr;
    }
}

@media (max-width: 700px) {
    /* PB-02C. Fourteen rules in two columns of ~150px is unreadable long
       before the viewport gets this narrow. One column, full measure. */
    .cs-public .cs-public__rules {
        grid-template-columns: 1fr;
    }

    .cs-public {
        --csp-display: 32px;
        --csp-h2: 24px;
        --csp-lede: 17px;
        --csp-band: 48px;
        --csp-gutter: 18px;
    }

    .cs-public .cs-public__headline {
        max-width: none;
    }

    /* §19. THE CTA GOES FULL WIDTH RATHER THAN STAYING PROMINENT BY LUCK.
       A pill button at 390px is a thumb-sized target in the middle of a
       column; a full-width one cannot be missed and cannot be mis-hit. */
    .cs-public .cs-public__cta {
        display: flex;
        width: 100%;
    }

    /* ...except the one in the header, which is beside the brand and must
       stay a button rather than swallowing the row. */
    .cs-public .cs-public__cta--sm {
        display: inline-flex;
        width: auto;
    }
}

@media (max-width: 560px) {
    .cs-public .cs-public__steps {
        grid-template-columns: 1fr;
    }

    /* PB-02C. One photograph per row. A 3:2 tile at half of 390px is 170px
       wide — too small to show what a court looks like, which is the only
       reason the photograph is there. */
    .cs-public .cs-public__gallery {
        grid-template-columns: 1fr;
    }

    .cs-public .cs-public__photo:first-child {
        aspect-ratio: 3 / 2;
    }

    .cs-public .cs-public__footer-inner {
        grid-template-columns: 1fr;
        gap: var(--cs-space-lg);
    }

    /* The hero crop tightens on a tall, narrow viewport: cover on a portrait
       box keeps far less of the frame's width, so the anchor moves back
       toward the middle to hold the courts rather than the near floor. */
    .cs-public .cs-public__hero--photo {
        background-position: center 55%;
    }

    /* At 390px the brand and a two-item nav do not share a row. The nav drops
       beneath it and spreads, which keeps both touch targets full size —
       shrinking them to fit is what §19 rules out. */
    .cs-public .cs-public__nav {
        width: 100%;
        justify-content: space-between;
    }
}

/* §20. Respect a reduced-motion preference. There is no animation on this page
   today; the smooth scroll below is the one thing that could become one, so it
   is opted into rather than assumed. */
@media (prefers-reduced-motion: no-preference) {
    .cs-public {
        scroll-behavior: smooth;
    }
}

/* The sticky header would otherwise cover the heading of whichever section the
   CTA jumps to. */
.cs-public .cs-public__section {
    scroll-margin-top: 84px;
}

/* =========================================================================
   PB-03 — the public availability matrix
   =========================================================================

   Added to the PUBLIC stylesheet, still under `.cs-public`, still with no
   `body`, `.btn`, `.card` or `table` rule of its own. §41: the internal 113KB
   stylesheet is not loaded here and the frozen internal UI cannot be reached
   from any selector below.

   Note the matrix's own rules are `.cs-book__matrix ...` rather than bare
   `table` / `th` / `td` — a bare element rule would be exactly the kind that
   escapes a component.                                                        */

.cs-public .cs-book__head {
    padding: 40px 0 0;
}

.cs-public .cs-book__title {
    margin: 0 0 var(--cs-space-xs);
    font-size: var(--csp-h2);
    font-weight: 800;
    color: var(--cs-brand-ink);
}

.cs-public .cs-book__hours {
    margin: 0 0 var(--cs-space-xl);
    color: var(--cs-text-muted);
}

/* ---------------------------------------------------------------- dates */

.cs-public .cs-book__dates {
    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: var(--cs-space-sm);
}

.cs-public .cs-book__step,
.cs-public .cs-book__today {
    min-height: var(--cs-touch-target);
    min-width: var(--cs-touch-target);
    padding: 0 14px;
    border: 1px solid var(--cs-border-strong);
    border-radius: var(--cs-radius-md);
    background: var(--cs-surface);
    color: var(--cs-brand-primary);
    font-size: var(--cs-font-md);
    font-weight: 700;
    cursor: pointer;
}

.cs-public .cs-book__step:hover:not(:disabled),
.cs-public .cs-book__today:hover {
    background: var(--cs-brand-primary-soft);
}

/* A DISABLED STEP SAYS SO IN MORE THAN COLOUR.
 *
 * The control is genuinely disabled, so it is removed from the tab order and
 * announced as unavailable — the dimming is the visual echo of a state the
 * browser already exposes, not the state itself. §44. */
.cs-public .cs-book__step:disabled {
    opacity: .45;
    cursor: not-allowed;
}

.cs-public .cs-book__date-field {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.cs-public .cs-book__date-label {
    font-size: var(--cs-font-xs);
    font-weight: 800;
    letter-spacing: .10em;
    text-transform: uppercase;
    color: var(--cs-text-muted);
}

.cs-public .cs-book__date {
    min-height: var(--cs-touch-target);
    padding: 0 12px;
    border: 1px solid var(--cs-border-strong);
    border-radius: var(--cs-radius-md);
    background: var(--cs-surface);
    color: var(--cs-text);
    font: inherit;
    font-size: var(--cs-font-md);
}

.cs-public .cs-book__day {
    margin: var(--cs-space-md) 0 0;
    font-size: var(--csp-lede);
    font-weight: 700;
    color: var(--cs-brand-ink);
}

/* --------------------------------------------------------------- legend */

.cs-public .cs-book__legend {
    list-style: none;
    margin: var(--cs-space-lg) 0 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--cs-space-lg);
}

.cs-public .cs-book__legend-item {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: var(--cs-font-base);
    color: var(--cs-text-muted);
}

.cs-public .cs-book__swatch {
    width: 16px;
    height: 16px;
    border-radius: var(--cs-radius-sm);
    border: 1px solid var(--cs-border-strong);
    flex: 0 0 auto;
}

.cs-public .cs-book__swatch--free { background: var(--cs-surface); }
.cs-public .cs-book__swatch--taken { background: var(--cs-surface-muted); }

.cs-public .cs-book__swatch--picked {
    background: var(--cs-brand-accent);
    border-color: var(--cs-brand-primary);
}

/* ----------------------------------------------------------- the matrix */

.cs-public .cs-book__body {
    padding: var(--cs-space-xl) var(--csp-gutter) var(--csp-band);
}

.cs-public .cs-book__status {
    margin: 0 0 var(--cs-space-md);
    padding: 12px 16px;
    border-radius: var(--cs-radius-md);
    background: var(--cs-surface-muted);
    color: var(--cs-text);
    font-size: var(--cs-font-md);
}

.cs-public .cs-book__status--error {
    background: var(--cs-brand-secondary-soft);
    color: var(--cs-brand-secondary-ink);
    border-left: 4px solid var(--cs-brand-secondary-ink);
}

/* §42. THE MATRIX SCROLLS; THE DOCUMENT DOES NOT.
 *
 * Nineteen hourly columns at a tappable size is roughly 1,300px, which no phone
 * has. The two wrong answers are to shrink the cells until they cannot be hit
 * and to let <body> scroll sideways. This container owns the overflow, so the
 * page stays put and only the grid moves. */
.cs-public .cs-book__scroll {
    overflow-x: auto;
    overflow-y: hidden;
    border: 1px solid var(--cs-border);
    border-radius: var(--cs-radius-lg);
    background: var(--cs-surface);

    /* Momentum scrolling on iOS, and a visible focus ring when a keyboard
       visitor tabs to the region to scroll it. */
    -webkit-overflow-scrolling: touch;
}

.cs-public .cs-book__scroll:focus-visible {
    outline: 3px solid var(--cs-focus-color);
    outline-offset: 2px;
}

.cs-public .cs-book__matrix {
    border-collapse: separate;
    border-spacing: 0;
    width: 100%;
}

.cs-public .cs-book__corner,
.cs-public .cs-book__hour,
.cs-public .cs-book__court {
    background: var(--cs-surface);
    font-size: var(--cs-font-sm);
    font-weight: 800;
    color: var(--cs-text-muted);
    text-align: center;
    white-space: nowrap;
    padding: 10px 8px;
    border-bottom: 1px solid var(--cs-border);
}

/* THE COURT COLUMN IS STICKY.
 *
 * §42 asks that court identity stay understandable while the grid scrolls. A
 * visitor who has scrolled to 9 PM must still know which row is Court 4; a
 * legend at the top of a scrolled-away column does not help. */
.cs-public .cs-book__corner,
.cs-public .cs-book__court {
    position: sticky;
    left: 0;
    z-index: 1;
    text-align: left;
    min-width: 132px;
    color: var(--cs-brand-ink);
    border-right: 1px solid var(--cs-border);
}

.cs-public .cs-book__cell {
    padding: 3px;
    border-bottom: 1px solid var(--cs-border);
    text-align: center;
}

.cs-public .cs-book__pick,
.cs-public .cs-book__cell--taken .cs-book__mark {
    display: flex;
    align-items: center;
    justify-content: center;

    /* §43. 44x44, the same touch floor the rest of the public site keeps. The
       temptation on a 19-column grid is to shave this to fit more on screen;
       the scroll container exists precisely so that it does not have to be. */
    min-width: var(--cs-touch-target);
    min-height: var(--cs-touch-target);
    width: 100%;
    border-radius: var(--cs-radius-sm);
}

.cs-public .cs-book__pick {
    border: 1px solid var(--cs-border-strong);
    background: var(--cs-surface);
    color: var(--cs-success);
    font-size: var(--cs-font-md);
    font-weight: 800;
    cursor: pointer;
}

.cs-public .cs-book__pick:hover {
    background: var(--cs-brand-primary-soft);
    border-color: var(--cs-brand-primary);
}

.cs-public .cs-book__pick:focus-visible {
    outline: 3px solid var(--cs-focus-color);
    outline-offset: 2px;
}

/* SELECTED, IN THREE WAYS AT ONCE.
 *
 * §24 and §44 both refuse colour-only state. The cell changes fill AND gains a
 * ring AND carries aria-pressed="true" — so it is distinguishable to someone
 * who cannot tell gold from white, and announced to someone who cannot see it
 * at all. */
.cs-public .cs-book__pick--on {
    background: var(--cs-brand-accent);
    border-color: var(--cs-brand-primary);
    color: var(--cs-brand-primary);
    box-shadow: inset 0 0 0 2px var(--cs-brand-primary);
}

.cs-public .cs-book__cell--taken .cs-book__mark {
    background: var(--cs-surface-muted);
    color: var(--cs-text-muted);
    font-size: var(--cs-font-md);
    font-weight: 700;

    /* Not a button, not focusable, nothing to press. */
    cursor: default;
}

/* -------------------------------------------------------------- summary */

.cs-public .cs-book__summary {
    background: var(--cs-bg);
    border-top: 1px solid var(--cs-border);
    padding: var(--csp-band) 0;
}

.cs-public .cs-book__summary-title {
    margin: 0 0 var(--cs-space-md);
    font-size: var(--csp-h2);
    font-weight: 800;
    color: var(--cs-brand-ink);
}

.cs-public .cs-book__picks {
    list-style: none;
    margin: 0 0 var(--cs-space-md);
    padding: 0;
    display: grid;
    gap: var(--cs-space-sm);
    max-width: 560px;
}

.cs-public .cs-book__pick-item {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--cs-space-sm);
    padding: 12px 16px;
    background: var(--cs-surface);
    border: 1px solid var(--cs-border);
    border-radius: var(--cs-radius-md);
}

.cs-public .cs-book__pick-court { font-weight: 800; color: var(--cs-brand-ink); }
.cs-public .cs-book__pick-when { color: var(--cs-text); }

.cs-public .cs-book__count {
    margin: 0 0 var(--cs-space-lg);
    font-weight: 700;
    color: var(--cs-brand-ink);
}

.cs-public .cs-book__notice {
    margin: 0 0 var(--cs-space-sm);
    max-width: 60ch;
    color: var(--cs-text-muted);
}

.cs-public .cs-book__notice--next {
    color: var(--cs-brand-ink);
    font-weight: 700;
}

.cs-public .cs-book__clear {
    min-height: var(--cs-touch-target);
    margin-top: var(--cs-space-md);
    padding: 0 20px;
    border: 1px solid var(--cs-brand-primary);
    border-radius: 999px;
    background: transparent;
    color: var(--cs-brand-primary);
    font-size: var(--cs-font-base);
    font-weight: 700;
    cursor: pointer;
}

.cs-public .cs-book__clear:hover {
    background: var(--cs-brand-primary);
    color: var(--cs-text-inverse);
}

/* THE GRID DIMS WHILE A NEW DATE LOADS.
 *
 * §31 asks that stale availability must not keep looking authoritative. The
 * status line says "Loading availability…"; this makes the old grid look
 * provisional at a glance, and pointer-events:none stops a visitor selecting a
 * cell that is about to be replaced by a different date's answer. */
.cs-public .cs-book--loading .cs-book__scroll {
    opacity: .45;
    pointer-events: none;
}

/* ---------------------------------------------------------- responsive */

@media (max-width: 700px) {
    .cs-public .cs-book__head { padding-top: 28px; }

    .cs-public .cs-book__dates { gap: 6px; }

    /* The date field takes the whole row so the native picker is comfortable,
       with the two arrows and Today beneath it.
     *
     * ORDER MATTERS HERE, AND THE FIRST ATTEMPT GOT IT WRONG. The field is
     * second in the DOM - between the two arrows, which is the right reading
     * order on a wide screen. Simply making it full width therefore left the
     * back arrow stranded alone on the row above it and pushed the forward
     * arrow onto a third row: three rows to change a date, and a control
     * floating with nothing beside it. `order` moves the field to the top of
     * the wrapped stack without touching the source order, so a screen reader
     * and a keyboard still meet the three in the sequence the markup sets. */
    .cs-public .cs-book__date-field { order: -1; flex: 1 1 100%; }
    .cs-public .cs-book__date { width: 100%; }

    .cs-public .cs-book__court,
    .cs-public .cs-book__corner { min-width: 108px; }
}

/* =========================================================================
   PB-04-A02 — public account forms
   =========================================================================

   Still under `.cs-public`, still no bare element rules. The internal
   stylesheet is not loaded here, so nothing may lean on `.cs-field`,
   `.cs-input` or any other internal primitive - these are the public site's
   own, and the first draft of the registration page reached for the internal
   ones and would have rendered unstyled.                                      */

.cs-public .cs-account__wrap {
    width: 100%;
    max-width: 560px;
    margin: 0 auto;
    padding: var(--csp-band) var(--csp-gutter);
}

.cs-public .cs-account__title {
    margin: 0 0 var(--cs-space-xs);
    font-size: var(--csp-h2);
    font-weight: 800;
    color: var(--cs-brand-ink);
}

.cs-public .cs-account__lede {
    margin: 0 0 var(--cs-space-xl);
    color: var(--cs-text-muted);
}

.cs-public .cs-account__form {
    display: grid;
    gap: var(--cs-space-lg);
}

/* Two names on one row where there is room, stacked where there is not. */
.cs-public .cs-account__row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--cs-space-lg);
}

.cs-public .cs-account__field {
    display: grid;
    gap: 6px;
}

.cs-public .cs-account__label {
    font-size: var(--cs-font-sm);
    font-weight: 800;
    color: var(--cs-brand-ink);
}

.cs-public .cs-account__optional {
    font-weight: 600;
    color: var(--cs-text-muted);
}

.cs-public .cs-account__input {
    min-height: var(--cs-touch-target);
    padding: 0 12px;
    border: 1px solid var(--cs-border-strong);
    border-radius: var(--cs-radius-md);
    background: var(--cs-surface);
    color: var(--cs-text);
    font: inherit;
    font-size: var(--csp-body);
    width: 100%;
}

.cs-public .cs-account__input:focus-visible {
    outline: 3px solid var(--cs-focus-color);
    outline-offset: 2px;
}

.cs-public .cs-account__help {
    margin: 0;
    font-size: var(--cs-font-sm);
    color: var(--cs-text-muted);
}

/* The failure summary. Colour AND a bar AND words - never colour alone. */
.cs-public .cs-account__error {
    padding: 12px 16px;
    border-radius: var(--cs-radius-md);
    border-left: 4px solid var(--cs-brand-secondary-ink);
    background: var(--cs-brand-secondary-soft);
    color: var(--cs-brand-secondary-ink);
}

.cs-public .cs-account__error-line {
    margin: 0;
    font-weight: 700;
}

.cs-public .cs-account__submit {
    min-height: 48px;
    margin-top: var(--cs-space-sm);
    padding: 0 28px;
    border: 0;
    border-radius: 999px;
    background: var(--cs-brand-accent);
    color: var(--cs-brand-primary);
    font-size: var(--csp-lede);
    font-weight: 800;
    cursor: pointer;
}

.cs-public .cs-account__submit:hover {
    background: var(--cs-brand-accent-amber);
}

.cs-public .cs-account__done {
    padding: var(--csp-band) 0;
}

.cs-public .cs-account__done-note {
    margin: 0 0 var(--cs-space-md);
    max-width: 60ch;
    color: var(--cs-text-muted);
}

@media (max-width: 560px) {
    .cs-public .cs-account__row {
        grid-template-columns: 1fr;
    }
}

/* =========================================================================
   PB-04-A03 — SIGN IN, SIGN OUT, AND A PRESERVED SELECTION
   ========================================================================= */

/* The header's authentication entries.
 *
 * The sign-out control is a BUTTON inside a form, because ending a session is a
 * POST - so it is styled to sit in the nav beside the anchors rather than
 * looking like the form control it is. It keeps the same 44px target and the
 * same focus treatment; nothing here removes an affordance to make it match. */
.cs-public .cs-public__nav-signout {
    display: inline-flex;
    margin: 0;
}

.cs-public .cs-public__nav-signout-btn {
    border: 0;
    background: transparent;
    font: inherit;
    font-weight: 700;
    color: var(--cs-text);
    cursor: pointer;
}

.cs-public .cs-public__nav-signout-btn:hover {
    color: var(--cs-brand-primary);
    background: var(--cs-brand-primary-soft);
}

/* The customer's name, which must not be mistaken for a section link. */
.cs-public .cs-public__nav-link--account {
    color: var(--cs-brand-ink);
}

.cs-public .cs-public__nav-name {
    max-width: 18ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cs-public .cs-public__nav-link--signin {
    border: 1px solid var(--cs-brand-primary);
    color: var(--cs-brand-primary);
}

/* ------------------------------------------------------- preserved selection */

/* WHAT WAS KEPT WHILE THEY SIGNED IN. A band above the date controls, because
   it explains the state of the page they are arriving at. */
.cs-public .cs-book__restored {
    padding: var(--cs-space-lg) 0;
    background: var(--cs-brand-primary-soft);
    border-bottom: 1px solid var(--cs-border);
}

.cs-public .cs-book__restored-title {
    margin: 0 0 6px;
    font-size: var(--csp-lede);
    color: var(--cs-brand-ink);
}

.cs-public .cs-book__restored-note {
    margin: 0 0 4px;
    max-width: 70ch;
    color: var(--cs-text);
}

/* Hours that were taken while they signed in. A LEFT BAR AND WORDS, not colour
   alone - the same rule the registration error block follows. */
.cs-public .cs-book__restored-note--dropped {
    padding-left: 12px;
    border-left: 4px solid var(--cs-brand-secondary-ink);
    color: var(--cs-brand-secondary-ink);
    font-weight: 700;
}

/* ------------------------------------------------------- continue to sign in */

.cs-public .cs-book__continue {
    margin: var(--cs-space-md) 0 0;
}

.cs-public .cs-book__continue-btn {
    min-height: 48px;
    padding: 0 28px;
    border: 0;
    border-radius: 999px;
    background: var(--cs-brand-accent);
    color: var(--cs-brand-primary);
    font-size: var(--csp-lede);
    font-weight: 800;
    cursor: pointer;
}

.cs-public .cs-book__continue-btn:hover {
    background: var(--cs-brand-accent-amber);
}

.cs-public .cs-book__continue .cs-book__notice--next {
    margin-top: var(--cs-space-sm);
    font-weight: 600;
    color: var(--cs-text-muted);
}

.cs-public .cs-book__notice-link {
    color: var(--cs-brand-primary);
    font-weight: 800;
}

/* ----------------------------------------------------------- account page */

.cs-public .cs-account__alt {
    margin: var(--cs-space-lg) 0 0;
    color: var(--cs-text-muted);
}

.cs-public .cs-account__alt-link {
    color: var(--cs-brand-primary);
    font-weight: 800;
}

.cs-public .cs-account__facts {
    display: grid;
    gap: var(--cs-space-md);
    margin: var(--cs-space-lg) 0;
}

.cs-public .cs-account__fact {
    padding: 12px 16px;
    background: var(--cs-surface);
    border: 1px solid var(--cs-border);
    border-radius: var(--cs-radius-md);
}

.cs-public .cs-account__fact-label {
    margin: 0 0 2px;
    font-size: var(--cs-font-sm);
    font-weight: 800;
    color: var(--cs-text-muted);
}

.cs-public .cs-account__fact-value {
    margin: 0;
    font-weight: 700;
    color: var(--cs-brand-ink);
}

/* Sign out on the account page is a real action but not the page's purpose, so
   it is quieter than the accent submit without becoming a control nobody can
   find. */
.cs-public .cs-account__submit--quiet {
    background: transparent;
    border: 1px solid var(--cs-brand-primary);
    color: var(--cs-brand-primary);
    font-size: var(--cs-font-base);
}

.cs-public .cs-account__submit--quiet:hover {
    background: var(--cs-brand-primary);
    color: var(--cs-text-inverse);
}

/* PB-08B — cancelling your own booking.
   =========================================================================
   The destructive action is deliberately NOT the accent pill every other
   submit uses: an outline in the warning ink reads as "this undoes
   something" without shouting, and it cannot be mistaken for the Book
   button a customer presses far more often. Colour is never the only
   signal - the button says "Cancel reservation" in words.                */
.cs-public .cs-account__submit--danger {
    background: transparent;
    border: 1px solid var(--cs-brand-secondary-ink);
    color: var(--cs-brand-secondary-ink);
    font-size: var(--cs-font-base);
}

.cs-public .cs-account__submit--danger:hover {
    background: var(--cs-brand-secondary-ink);
    color: var(--cs-text-inverse);
}

/* The outcome of a cancellation attempt, carried across the redirect.
   Same bar-plus-words construction as the account error summary.        */
.cs-public .cs-account__notice {
    margin: 0 0 var(--cs-space-md);
    padding: 12px 16px;
    max-width: 60ch;
    border-radius: var(--cs-radius-md);
    border-left: 4px solid var(--cs-brand-primary);
    background: var(--cs-surface-muted, transparent);
    font-weight: 700;
}

.cs-public .cs-account__notice--done {
    border-left-color: var(--cs-brand-accent);
}

.cs-public .cs-account__notice--warn {
    border-left-color: var(--cs-brand-secondary-ink);
    color: var(--cs-brand-secondary-ink);
    background: var(--cs-brand-secondary-soft);
}

/* =========================================================================
   PB-07 — MY BOOKINGS
   =========================================================================
   Built from the account-page primitives. The list tab in use is marked by
   aria-current AND an underline AND weight - never colour alone. */

.cs-public .cs-bookings__wrap {
    max-width: 720px;
}

.cs-public .cs-bookings__tabs {
    display: flex;
    gap: var(--cs-space-sm);
    margin: var(--cs-space-md) 0 var(--cs-space-lg);
    border-bottom: 1px solid var(--cs-border);
}

.cs-public .cs-bookings__tab {
    display: inline-flex;
    align-items: center;
    min-height: var(--cs-touch-target);
    padding: 0 16px;
    border-bottom: 3px solid transparent;
    color: var(--cs-text);
    font-weight: 700;
    text-decoration: none;
}

.cs-public .cs-bookings__tab[aria-current="page"] {
    border-bottom-color: var(--cs-brand-primary);
    color: var(--cs-brand-ink);
    font-weight: 800;
}

.cs-public .cs-bookings__tab:focus-visible,
.cs-public .cs-bookings__card-link:focus-visible {
    outline: 3px solid var(--cs-focus-color);
    outline-offset: 2px;
}

.cs-public .cs-bookings__heading {
    margin: 0 0 var(--cs-space-md);
    font-size: var(--csp-lede);
    color: var(--cs-brand-ink);
}

.cs-public .cs-bookings__list {
    display: grid;
    gap: var(--cs-space-md);
    margin: 0 0 var(--cs-space-lg);
    padding: 0;
    list-style: none;
}

.cs-public .cs-bookings__card {
    padding: 16px;
    background: var(--cs-surface);
    border: 1px solid var(--cs-border);
    border-radius: var(--cs-radius-md);
}

.cs-public .cs-bookings__card-title {
    margin: 0 0 var(--cs-space-sm);
    font-size: var(--csp-body);
    font-weight: 800;
    color: var(--cs-brand-ink);
}

.cs-public .cs-bookings__card-link {
    color: var(--cs-brand-primary);
}

/* Label over value, two columns where there is room, one where there is not. */
.cs-public .cs-bookings__meta {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--cs-space-sm) var(--cs-space-lg);
    margin: 0;
}

.cs-public .cs-bookings__meta dt {
    font-size: var(--cs-font-sm);
    font-weight: 800;
    color: var(--cs-text-muted);
}

.cs-public .cs-bookings__meta dd {
    margin: 0;
    font-weight: 700;
    color: var(--cs-brand-ink);
    overflow-wrap: anywhere;
}

.cs-public .cs-bookings__pager {
    display: flex;
    align-items: center;
    gap: var(--cs-space-lg);
    margin: 0 0 var(--cs-space-lg);
}

.cs-public .cs-bookings__lines {
    margin: 0;
    padding-left: 1.1em;
}

.cs-public .cs-bookings__breakdown {
    width: 100%;
    margin: 0 0 var(--cs-space-lg);
    border-collapse: collapse;
}

.cs-public .cs-bookings__breakdown caption {
    margin-bottom: var(--cs-space-sm);
    text-align: left;
    font-weight: 800;
    color: var(--cs-brand-ink);
}

.cs-public .cs-bookings__breakdown th,
.cs-public .cs-bookings__breakdown td {
    padding: 8px 12px 8px 0;
    border-bottom: 1px solid var(--cs-border);
    text-align: left;
}

.cs-public .cs-bookings__back {
    margin: 0 0 var(--cs-space-sm);
}

@media (max-width: 560px) {
    .cs-public .cs-bookings__meta {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* =========================================================================
   PB-04B — PROVIDER SIGN IN
   ========================================================================= */

/* The "or" rule between the local form and the provider buttons. A line with a
   word in it, built from a border rather than an image. */
.cs-public .cs-account__divider {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: var(--cs-space-lg) 0;
    color: var(--cs-text-muted);
}

.cs-public .cs-account__divider::before,
.cs-public .cs-account__divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--cs-border);
}

.cs-public .cs-account__divider-text {
    font-size: var(--cs-font-sm);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
}

/* THE PROVIDER BUTTON.
 *
 * A neutral surface with the provider's own mark, which is what Google's brand
 * guidance asks for and also what stops the page looking like it is operated by
 * Google. 48px tall, above the 44px touch floor, like every other primary
 * control on this site. */
.cs-public .cs-account__provider {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;

    min-height: 48px;
    padding: 0 20px;

    /* 3.68:1 against the page, because this border IS the button - see the token. */
    border: 1px solid var(--csp-border-control);
    border-radius: 999px;

    background: var(--cs-surface);
    color: var(--cs-text);

    font-size: var(--cs-font-base);
    font-weight: 700;
    text-decoration: none;
}

.cs-public .cs-account__provider:hover {
    background: var(--cs-brand-primary-soft);
    border-color: var(--cs-brand-primary);
}

.cs-public .cs-account__provider:focus-visible {
    outline: 3px solid var(--cs-focus-color);
    outline-offset: 2px;
}

/* The mark keeps its own colours - it is a trademark, not an icon to theme. */
.cs-public .cs-account__provider-mark {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
}

/* PB-04C. The second provider button sits under the first with the same rhythm
   the form's fields use. Both share every other rule - the surface, the border
   contrast, the 48px target and the focus ring - because they are the same
   control offered twice, and a customer should not have to work out why one
   looks different. */
.cs-public .cs-account__provider + .cs-account__provider {
    margin-top: var(--cs-space-md);
}
