/* Generic components, ported from ExchangeCertificates components.css (same class names, same
   behaviour) so the Kolekt products read as one family. Page-specific rules live in their own sheets. */

/* Cross-page components: hero, stat tile, pool card, empty state, toast, pagination. */

/* Asymmetric on purpose (16.09.2026): the customer asked for the title higher and the cards closer,
   so the top is 1.5rem over .site-main's own 2rem, and the bottom carries the whole gap to the filter
   bar - .hero__note no longer adds a second one under it. Measured: 80 -> 56px above the title,
   72 -> 32px under the note. */

/* padding-block, not the shorthand: the hero is also a .container, and a horizontal 0 here took
   away the gutter every other section keeps - the title and the note ran to the phone's edge. */

.hero { text-align: center; padding-block: var(--sp-5) var(--sp-6); }

.hero__title { font-size: var(--fs-600); margin-bottom: var(--sp-3); }

.hero__subtitle { color: var(--color-text-muted); max-width: 46rem; margin: 0 auto var(--sp-2); }

/* The line under the subtitle (Corrections 160). No bottom margin: the hero's own padding is what
   separates it from the filter bar, and two of them is what made that gap 72px. */

.hero__note { font-size: var(--fs-200); color: var(--color-text-muted); max-width: 46rem; margin: 0 auto; }

.stat-grid { display: grid; gap: var(--sp-4);
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); margin-bottom: var(--sp-6); }
.stat-grid[hidden] { display: none; }

.stat-tile { background: var(--color-surface); border: 1px solid var(--color-border);
    border-radius: var(--radius); padding: var(--sp-4); border-left: 4px solid var(--color-border); }

.stat-tile__value { font-size: var(--fs-500); font-weight: 700; color: var(--c-navy);
    font-variant-numeric: tabular-nums; }

.stat-tile__label { font-size: var(--fs-200); color: var(--color-text-muted); }

/* The left accent is the ledger state, so a glance tells available from merely reserved. */

.stat-tile--available { border-left-color: var(--state-available); }

.stat-tile--reserved { border-left-color: var(--state-reserved); }

.stat-tile--sold { border-left-color: var(--state-sold); }

.stat-tile--chained { border-left-color: var(--state-chained); }

.stat-tile--unbacked { border-left-color: var(--state-unbacked); }

/* A tile that counts a set is an <a> and goes to that set (CLAUDE.md section 6). Two things have
   to be true and neither is free:

   - It must not look like a link. Without this it inherits a { color: var(--c-blue-dark) } and the
     number turns blue on exactly the tiles that changed.
   - A tile with nothing to show must not be clickable. The page drops the href at zero, and an <a>
     without one is neither focusable nor a link - so :not([href]) drops the affordance with it.
     A link to an empty list is a question with no answer. */

a.stat-tile {
    color: inherit;
    text-decoration: none;
    transition: border-color var(--dur-fast) ease, box-shadow var(--dur-fast) ease;
}

a.stat-tile[href]:hover { box-shadow: var(--shadow-sm); border-color: var(--c-blue); }

a.stat-tile[href]:focus-visible { outline: 3px solid var(--c-blue); outline-offset: 2px; }

a.stat-tile:not([href]) { cursor: default; }

/* --- Tab strip -----------------------------------------------------------
 * The buttons are .btn variants, which is what admin/config already did; there is no .tab class
 * and inventing one would restyle a control that already looks right. This only lays them out. */

.tab-strip {
    display: flex;
    gap: var(--sp-2);
    flex-wrap: wrap;
    margin-bottom: var(--sp-5);
}

.tab-strip[hidden] { display: none; }

.empty-state { text-align: center; padding: var(--sp-7) var(--sp-4); color: var(--color-text-muted); }

.pagination { display: flex; gap: var(--sp-2); justify-content: center; margin-top: var(--sp-5); }

.pagination[hidden] { display: none; }

.pagination__page { padding: var(--sp-2) var(--sp-3); border: 1px solid var(--color-border);
    border-radius: var(--radius-sm); background: var(--color-surface); cursor: pointer; font: inherit; }

.pagination__page--active { background: var(--c-navy); color: var(--c-white); border-color: var(--c-navy); }

/* Toast. Fixed and stacked, so a slow request cannot push the page around when it lands.
 * The bottom offset clears the docked tab bar; --bottom-nav-h is 0px when there is no bar, so on a
 * desktop this is still var(--sp-4). A toast outranks the bar on z-index and would have been drawn
 * ON TOP of it - readable, but sitting over the navigation with its own shadow. */

.toast-stack { position: fixed; right: var(--sp-4); bottom: calc(var(--sp-4) + var(--bottom-nav-h));
    z-index: var(--z-toast);
    display: flex; flex-direction: column; gap: var(--sp-2); max-width: 22rem; }
.toast-stack[hidden] { display: none; }

.toast { padding: var(--sp-3) var(--sp-4); border-radius: var(--radius-sm);
    box-shadow: var(--shadow); background: var(--c-navy); color: var(--c-white); font-size: var(--fs-200); }

.toast--error { background: var(--color-danger); }

.toast--success { background: var(--c-green-dark); }

/* Gate banner. The operator approval gate decides whether the whole account can do anything at
 * all, so its state is carried by colour as well as words: grey until it is known, yellow while
 * it is waiting, green when it is open, red when it is closed. */

/* A banner is always followed by the thing it is talking about, so it owns the gap. Without this
   every call site carried its own inline margin - the last inline style left on those screens. */

/* position:relative so a corner control has something to anchor to - .card does not set it, which
   was checked rather than assumed. padding-right leaves the x a lane of its own, or a long message
   runs underneath it. */

.gate-banner {
    position: relative;
    border-left: 4px solid var(--c-gray);
    margin-bottom: var(--sp-5);
    padding-right: calc(var(--sp-5) + 2rem);
}

.gate-banner.is-waiting { border-left-color: var(--c-yellow); }

.gate-banner.is-approved { border-left-color: var(--c-green); }

.gate-banner.is-blocked { border-left-color: var(--color-danger); }

/* Companion guard for the badge in base.css: it is display:inline-block, and an author rule beats
 * the user agent's [hidden] rule - without this a badge toggled with el.hidden stays on screen. */

.badge[hidden] { display: none; }

/* --- Info tip ------------------------------------------------------------
 * The "?" beside a heading or a field label. It carries a sentence that used to sit on the page
 * as a paragraph.
 *
 * The sentence has not left the product: info-tip.js wires aria-describedby from the button to
 * the bubble, and a description is computed even from a display:none target - so a screen reader
 * still hears it without opening anything. It just stops costing every sighted reader a paragraph
 * they mostly already knew. */

/* vertical-align:middle is defined as "box centre on the baseline plus HALF THE X-HEIGHT", but the
   eye centres much higher than that - so the icon reads low, and the taller the heading the more it
   shows. The 0.22em is MEASURED, not derived: against the real line box of a 24px h2 the icon sat
   5.3px low, which is 0.22em, and it is expressed in em so the same rule holds next to an h1, an h2
   and a small field label without a second number. Re-measure with scripts/browser/info-tip.js if
   the type scale or the font ever changes. */

/* ⚠ The lift is on the BUTTON and must stay there. On the wrapper it made .info-tip the containing
   block for position:fixed descendants - a non-none transform does that - so the phone rule below
   resolved left/right against the 20px question mark instead of the viewport: width came out
   negative, the bubble collapsed to a ~34px strip and the sentence wrapped one character per line.
   The customer reported it as "the hover text is not readable". Moving it down one rule optically
   centres the same mark and leaves the wrapper an ordinary box. */

.info-tip {
    position: relative;
    display: inline-block;
    vertical-align: middle;
    margin-left: var(--sp-2);
}

/* Companion guard: the rule above is display:inline-block. */

.info-tip[hidden] { display: none; }

/* The mark is a 20px "i"; the button around it is a 32px target (44px on a touch screen) that takes
   only the mark's place in the line, so a heading keeps its rhythm. */
.info-tip__button {
    transform: translateY(-0.22em);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    margin: -0.375rem;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--color-text-muted);
    cursor: pointer;
}

/* Companion guard: the rule above is display:inline-flex. */

.info-tip__button[hidden] { display: none; }

@media (pointer: coarse) {
    .info-tip__button { width: 2.75rem; height: 2.75rem; margin: -0.75rem; }
}

.info-tip__icon {
    width: 1.25rem;
    height: 1.25rem;
    border-radius: 999px;
    background: var(--color-surface);
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    transition: background-color var(--dur-fast) ease, color var(--dur-fast) ease;
}

.info-tip__button:hover .info-tip__icon,
.info-tip.is-open .info-tip__icon { background: var(--c-yellow); color: var(--c-navy); }

.info-tip__button:focus-visible { outline: 3px solid var(--c-blue); outline-offset: -4px; }

/* A bubble of several lines (a ranking row's details): each line its own block. */
.info-tip__line { display: block; }
.info-tip__line + .info-tip__line { margin-top: var(--sp-1); }

/* NO [hidden] companion here, and that is deliberate: this rule sets no display at all, so the
   user agent's [hidden]{display:none} is what hides it. Adding display:block would silently break
   every tip on the site. Said out loud because every other block in this file needs a companion
   and the absence would otherwise read as an oversight. */

.info-tip__bubble {
    position: absolute;
    top: calc(100% + var(--sp-2));
    left: 0;
    z-index: var(--z-tip);
    width: max-content;
    max-width: 22rem;
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    box-shadow: var(--shadow);
    font-size: var(--fs-200);
    font-weight: 400;
    line-height: 1.5;
    color: var(--color-text);
    text-align: left;
    /* The tip often sits in a heading row that does not wrap; the bubble must. */
    white-space: normal;
}

/* Near the right edge the bubble would leave the viewport. Chosen per call site rather than
   measured: there is no layout pass to hook here and a hand-picked anchor is honest. */

.info-tip--end .info-tip__bubble { left: auto; right: 0; }

/* ⚠ A tip inside a scroll container cannot open downward.
 *
 * .table-scroll is overflow-x:auto, and per the overflow spec one axis that is not `visible` makes
 * the other `auto` too - so it is a vertical clipper as well. Every tip on the stock-balance header
 * and every tip on a to-do row lives inside one, opens downward, and was cut off at the bottom edge
 * of the table; the browser grew a scrollbar inside the table instead of showing the sentence. Same
 * family as the clipped-ancestor notes on .data-table and on the sticky header.
 *
 * The fix cannot be CSS alone - an absolutely positioned box is clipped by any such ancestor
 * whatever it is offset from - so info-tip.js detects the clipper, adds is-pinned and hands the
 * measured viewport coordinates in as custom properties. A VALUE through a custom property, not a
 * display rule: the [hidden] companion above still does the hiding.
 *
 * Scoped to min-width 481px so the phone rule below, which is the better answer on a small screen,
 * is not outranked by this one's higher specificity. */

@media (min-width: 481px) {
    .info-tip.is-pinned .info-tip__bubble {
        position: fixed;
        top: var(--tip-y, 0);
        left: var(--tip-x, 0);
        right: auto;
        max-width: min(22rem, calc(100vw - 2 * var(--sp-4)));
    }
}

@media (max-width: 480px) {
    /* On a narrow screen the bubble is pinned to the VIEWPORT, not to the tip.
     *
     * A tip can sit anywhere along a heading that has wrapped, and left:0 anchored to the tip with
     * a near-full-viewport max-width put nearly every bubble past the right edge - which gave the
     * whole page a horizontal scrollbar the moment one was opened. Measured at 390px it was up to
     * 296px of overflow on the auditor screen. .info-tip--end does not save it either: a
     * right-anchored bubble then overflows the LEFT edge instead.
     *
     * Anchoring to the bottom of the viewport also puts it where a thumb is, rather than under a
     * heading the keyboard may have scrolled away.
     *
     * Which is exactly where the docked tab bar now is. The bubble's z-index (--z-tip) is above the
     * bar's (--z-sticky), so it would have covered the navigation instead of disappearing under it
     * - the worse of the two failures, because a bubble that is dismissed by tapping elsewhere
     * would have eaten the taps meant for the tabs. It sits ON TOP of the bar instead:
     * --bottom-nav-h is the bar's height, and 0px on any screen that has no bar. */
    .info-tip__bubble,
    .info-tip--end .info-tip__bubble {
        position: fixed;
        top: auto;
        bottom: calc(var(--sp-4) + var(--bottom-nav-h));
        left: var(--sp-4);
        right: var(--sp-4);
        width: auto;
        max-width: none;
    }
}

/* A list of words, wrapping. Used for phases, materials, services and equipment - four lists whose
   only difference is where the words came from. */

.chip-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.chip-list[hidden] { display: none; }

.chip {
    padding: var(--sp-1) var(--sp-3);
    border-radius: 999px;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    font-size: var(--fs-100);
    color: var(--c-navy);
}

.chip[hidden] { display: none; }

/* ==========================================================================
   Certificate summary - the parts the rebuild added
   Folding bands, the operator columns, the pricing breakdown and the seven-
   column evidence table. The band, hero, chain, price and order styles above
   are unchanged and still do their job.
   ========================================================================== */

/* --- Folding bands ---------------------------------------------------------
 * Four independent disclosures, one of them open from the start. Deliberately
 * NOT window.KXC.tabs: tabs show one panel at a time, force mutual exclusivity
 * and own location.hash, and none of those is wanted here. Deliberately not a
 * <details> either - that cannot be driven by el.hidden, which is the only way
 * a panel in this codebase is allowed to disappear. */

/* A closed fold is a bar with nothing under it, and three of them stacked read as one solid block
   of colour rather than three things you can open. The hairline is what separates them. */

.fold + .fold > .fold__bar { border-top: 1px solid var(--color-surface); }

.fold[hidden] { display: none; }

.fold__bar { padding: 0; }

/* The button IS the bar, so the whole coloured strip is the hit area rather
   than the few words on it. */

.fold__toggle {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    width: 100%;
    padding: var(--sp-3) var(--sp-4);
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.fold__toggle[hidden] { display: none; }

.fold__toggle:focus-visible { outline: 3px solid var(--c-navy); outline-offset: -3px; }

.fold__caret {
    flex: 0 0 auto;
    width: 0;
    height: 0;
    border-top: 5px solid transparent;
    border-bottom: 5px solid transparent;
    border-left: 7px solid currentColor;
    transition: transform var(--dur-fast) ease;
}

.fold.is-open .fold__caret { transform: rotate(90deg); }

/* The Info fold on a work screen has to read as something you can press, not as a heading that
   happens to have a mark beside it (Corrections 84/85). Green is the colour of an action here.
   NOT --c-green: measured against the card surface the brand green gives 1.86:1 and the caret all
   but disappears, where --c-green-dark gives 5.34:1. The label goes with it, so the whole bar is
   one affordance rather than a green mark next to black text. */

.fold--boxed > .fold__bar > .fold__toggle { color: var(--action-ink); font-weight: 600; }

.fold--boxed > .fold__bar > .fold__toggle:hover { color: var(--c-navy); }

/* A count on the bar, so a closed fold still says how much is behind it. */

.fold__count { margin-left: auto; font-weight: 400; font-size: var(--fs-200); }

.fold__count[hidden] { display: none; }

.fold__panel[hidden] { display: none; }

/* A fold that stands on its own rather than sitting inside a band, so it draws its own box.
   The padding lives on the toggle and on the panel and NEVER on the root: a padded root would
   inset the bar from the edge the button is supposed to span, and two paddings meeting in the
   middle is how the gap under a card's last line got to be 32px once already. */

.fold--boxed {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    margin-bottom: var(--sp-5);
}

.fold--boxed[hidden] { display: none; }

.fold--boxed > .fold__panel { padding: 0 var(--sp-4) var(--sp-4); }

/* Red is the wireframe's, and it means "this needs you", not "this is broken". Applied only when
   the figure is above zero - a red 0 would be an alarm about nothing. */

.stat-tile__value.is-alert,
.data-table__cell.is-alert { color: var(--color-danger); }

/* A heading inside a card, below the card's own <h2>. Was an inline font-size; a
   class so the three that now use it cannot drift apart. */

.subhead {
    font-size: var(--fs-400);
    margin: 0 0 var(--sp-3);
}

/* --- Dismissing something from the dashboard ------------------------------
   A small x that takes the item off the list. The state is per viewer and lives in localStorage:
   it is a display preference, not a fact about the business, and the checklist itself is derived
   live on every request precisely so that no row can go stale. Storing a dismissal in the ledger
   would put a second, drifting copy of the truth next to the first. */

.dismiss {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--color-text-muted);
    font-size: var(--fs-300);
    line-height: 1;
    cursor: pointer;
}

.dismiss[hidden] { display: none; }

.dismiss:hover { background: var(--color-border); color: var(--c-navy); }

.dismiss:focus-visible { outline: 3px solid var(--c-blue); outline-offset: 2px; }

/* Top right of a banner. Its anchor is .gate-banner's own position:relative, added there for this;
   .card sets no position, so without it this would climb to whatever ancestor happened to be
   positioned and land somewhere else on the page entirely. */

.dismiss--corner {
    position: absolute;
    top: var(--sp-2);
    right: var(--sp-2);
}

/* Six across on a wide screen, wrapping down to two on a phone. auto-fit with a floor rather than
   a fixed six, so the row never produces a tile too narrow to read its own label. */

.stat-grid--six { grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); }

/* Seven in a row, which is what the proofs page needs and --six cannot give it: MEASURED,
   the grid there is 1088px inside a 1120px container with a 16px gap, so seven tiles have
   1088 - 6*16 = 992px between them, 141px each. A 9.5rem (152px) floor is over that, so the
   seventh tile dropped to a row of its own - one orphan under six, which is not a row of
   indicators. 8.5rem is 136px: seven fit with room to spare and 1fr spends the rest. */

.stat-grid--seven { grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr)); }

/* A proportion drawn as a bar. The width is the datum and is set per instance from a script; only
   the track and the ink are a rule, which is the line CLAUDE.md 6 draws - a VALUE may be inline, a
   display rule may not, because an inline display rule can have no [hidden] twin. */

.meter {
    height: 8px;
    border-radius: 999px;
    background: var(--color-border);
    overflow: hidden;
    margin: var(--sp-2) 0;
}

.meter[hidden] { display: none; }

.meter__fill { display: block; height: 100%; width: var(--meter-w, 0%); background: var(--c-green); }

/* The marketplace's pager: Previous, every page number, Next. It wraps instead of pushing the page
   sideways on a phone, and the step at either end stays in place, dimmed, so the numbers do not
   jump when it stops applying. */

.pagination--wrap { flex-wrap: wrap; }

.pagination__page:disabled { opacity: .45; cursor: default; }

/* --- account menu, add-role, password reset --- */

/* The account menu: the profile icon in the header's right corner for anyone signed in, and the menu
   it opens (fragments/header.html). header.js shows the menu, its panel and each item with el.hidden,
   so every display rule below has its [hidden] twin. */

.account-menu {
    position: relative;
    display: flex;
    flex: 0 0 auto;
    align-items: center;
}

.account-menu[hidden] { display: none; }

/* The burger's outline, and round: it reads as a person rather than as a second menu. 40px beside the
   inline nav, whose links are 40px tall, so the header keeps its height - measured, a 44px button
   made the wide header 76px instead of 72. Below the breakpoint it matches the 44px burger instead. */

.account-menu__button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    background: var(--color-surface);
    color: var(--c-navy);
    cursor: pointer;
    transition: background-color var(--dur-fast) ease;
}

.account-menu__button[hidden] { display: none; }

.account-menu__button:hover,
.account-menu.is-open .account-menu__button { background: var(--c-yellow); }

.account-menu__button:focus-visible { outline: 3px solid var(--c-blue); outline-offset: 2px; }

.account-menu__icon {
    display: block;
    width: 1.5rem;
    height: 1.5rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
}

.account-menu__icon[hidden] { display: none; }

/* Hangs from the button's right edge, so on a phone it opens inward and never off the screen: the
   cap is the viewport less the header's side padding at that width, on both sides. The header is
   the stacking context (--z-sticky), so 1 is enough to clear the nav panel beside it. */

.account-menu__panel {
    position: absolute;
    top: calc(100% + var(--sp-2));
    right: 0;
    z-index: 1;
    width: max-content;
    min-width: 15rem;
    max-width: min(20rem, calc(100vw - 2 * var(--sp-4)));
    padding-bottom: var(--sp-2);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}

.account-menu__who {
    display: grid;
    gap: 0.125rem;
    margin: 0;
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--color-border);
}

.account-menu__who[hidden] { display: none; }

/* A long address wraps inside the panel rather than pushing it past the screen edge. */

.account-menu__name { font-weight: 600; color: var(--c-navy); overflow-wrap: anywhere; }

.account-menu__email { font-size: var(--fs-200); color: var(--color-text-muted); overflow-wrap: anywhere; }

/* A badge is inline-block; as a grid item it would stretch the width of the panel. */

.account-menu__role { justify-self: start; margin-top: var(--sp-1); }

.account-menu__list {
    display: flex;
    flex-direction: column;
    padding-top: var(--sp-2);
}

.account-menu__list[hidden] { display: none; }

/* A row the width of the panel and 44px tall, the burger panel's own target. Links and buttons share
   it, so the button's font, border and alignment are reset to a link's. */

.account-menu__item {
    display: flex;
    align-items: center;
    width: 100%;
    min-height: 2.75rem;
    padding: var(--sp-2) var(--sp-4);
    border: 0;
    background: transparent;
    font: inherit;
    font-weight: 500;
    color: var(--c-navy);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}

.account-menu__item[hidden] { display: none; }

.account-menu__item:hover { background: var(--c-yellow); color: var(--c-navy); text-decoration: none; }

/* Inset, like the bottom bar's tabs: an outline outside the row would be cut off by the panel. */

.account-menu__item:focus-visible {
    outline: 3px solid var(--c-blue);
    outline-offset: -3px;
    background: var(--c-yellow);
}

.account-menu__item[disabled] { opacity: .5; cursor: progress; }

/* Log out stands apart from the moves above it - but only when something IS above it: an admin's
   menu is the identity and Log out, and a rule over a lone item reads as a missing one. */

.account-menu__item:not([hidden]) ~ .account-menu__item--end {
    margin-top: var(--sp-2);
    border-top: 1px solid var(--color-border);
}

/* Below the nav breakpoint (layout.css, 1219px - they move together) the nav is a panel on a row of
   its own. The account button follows the nav in the source, where a wide screen's tab order wants
   it; order puts the panel's row under the button, instead of the button under the open panel. */

@media (max-width: 1219px) {
    .account-menu__button { width: 2.75rem; height: 2.75rem; }
}

/* ==========================================================================
   Legal pages: privacy policy, cookie policy, legal notice
   ========================================================================== */

/* A document to read: one comfortable column, the same gutter as every page. A heading such as
   "Kolekt Certificates (certificates.kolekt.com)" carries a word with no break in it; with a
   phone's larger text setting it stood 168px wider than the screen and widened the whole page.
   break-word wraps such a word only when it cannot fit, so ordinary text is untouched. */

.legal-doc { max-width: 52rem; overflow-wrap: break-word; }

.legal-doc section { margin-top: var(--sp-6); scroll-margin-top: calc(var(--header-h, 4.5rem) + var(--sp-4)); }

.legal-doc h3 { margin-top: var(--sp-5); }

.legal-doc .table-scroll { margin-bottom: var(--sp-3); }

.legal-doc ul { padding-left: var(--sp-5); margin: 0 0 var(--sp-3); }

.legal-doc li { margin-bottom: var(--sp-1); }

/* Addresses and storage keys have no break opportunities; on a phone they must wrap, not widen. */

.legal-doc code { font-size: 0.9em; overflow-wrap: anywhere; }

.legal-toc { margin-top: var(--sp-4); }

.legal-toc ol { padding-left: var(--sp-5); margin: 0; columns: 2 16rem; column-gap: var(--sp-6); }

.legal-toc li { margin-bottom: var(--sp-1); break-inside: avoid; }

/* A real <table>: these are lists of facts a reader compares across rows. Column widths come from
   the content - a fixed share per column squeezed whichever column held the long text, and on a
   phone broke words mid-letter ("stora-ge"). Below 34rem the table keeps that width and scrolls
   inside .table-scroll instead: a table read sideways beats one read a syllable at a time, and the
   page itself never widens. */

.legal-table {
    width: 100%; min-width: 34rem;
    border-collapse: collapse; font-size: var(--fs-200); background: var(--color-surface);
}

.legal-table--two { min-width: 26rem; }

.legal-table th, .legal-table td {
    text-align: left; vertical-align: top;
    padding: var(--sp-2) var(--sp-3);
    border-bottom: 1px solid var(--color-border);
}

.legal-table th { background: var(--color-surface-alt); color: var(--color-text); font-weight: 600; }

/* Check badges: the class is derived from the value (badge--check-verified ...), like the proof
   status badges. UNCHECKED keeps the neutral badge on purpose - it is not a finding. */

.badge--check-verified { background: color-mix(in srgb, var(--c-green-dark) 12%, var(--c-white)); color: var(--c-green-dark); }

.badge--check-differs { background: var(--color-danger-bg); color: var(--color-danger); }

.badge--check-likely { background: var(--color-warning-bg); color: var(--color-warning); }

.badge--check-read_only { background: color-mix(in srgb, var(--c-blue) 14%, var(--c-white)); color: var(--c-blue-dark); }

/* A report nobody has approved yet is still waiting on somebody, so it wears the waiting colour
   beside held and pending. Published, accepted and replaced keep the neutral badge. */

.badge--status-waiting_for_review { background: var(--color-warning-bg); color: var(--color-warning); }

/* --- Legal draft markers (from ExchangeCertificates) ------------------------------------------
 * While a legal text is a draft it says so at the top, and every value still to be confirmed is
 * marked on the page, so a reviewer sees what is open instead of reading a guess as a fact. */
.legal-draft {
    padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-5);
    border-radius: var(--radius); border-left: 4px solid var(--c-yellow);
    background: color-mix(in srgb, var(--c-yellow) 14%, var(--color-surface));
    font-size: var(--fs-200);
}
.legal-todo { background: color-mix(in srgb, var(--c-yellow) 45%, transparent); padding: 0 0.2em; border-radius: 3px; }
