/* assets/css/style.css */
/* EasyShow Premium Obsidian & Glassmorphic Design System */

:root {
    /* RGB Definitions for translucency */
    --bg-base-rgb: 6, 9, 19;
    --bg-surface-rgb: 15, 19, 34;
    --bg-card-rgb: 20, 26, 46;
    --bg-overlay-rgb: 29, 36, 63;
    
    --accent-primary-rgb: 255, 122, 0;
    
    --text-primary-rgb: 243, 244, 246;
    --text-secondary-rgb: 156, 163, 175;
    --text-muted-rgb: 107, 114, 128;
    
    --border-color-rgb: 30, 37, 64;
    --border-highlight-rgb: 42, 51, 91;
    
    --color-my-dogs-rgb: 239, 68, 68;
    --color-important-rgb: 245, 158, 11;
    --color-orders-rgb: 59, 130, 246;
    --color-friends-rgb: 16, 185, 129;

    /* Color Palette */
    --bg-base: #060913;          /* Deep dark obsidian */
    --bg-surface: #0F1322;       /* Midnight blue-gray surface */
    --bg-card: #141A2E;          /* Muted card background */
    --bg-overlay: #1D243F;       /* Highlight overlays */
    
    --accent-primary: #FF7A00;   /* Premium Vibrant Orange */
    --accent-glow: rgba(255, 122, 0, 0.8);

    /* Halls after the first, which keeps the accent (DIM-812). */
    --hall-2: #16A34A;           /* green */
    --hall-3: #3B82F6;           /* blue */
    --hall-4: #A855F7;           /* violet */
    
    --text-primary: #F3F4F6;     /* Bright gray */
    --text-secondary: #9CA3AF;   /* Muted gray */
    --text-unlinked: #959CA9;    /* A name with nothing to open (Dimas, 2026-10-20) */
    --text-muted: #6B7280;       /* Darker muted gray */
    
    --border-color: #1E2540;     /* Sharp clean borders */
    --border-highlight: #2A335B; /* Accent borders */

    /* Fields you type into. Their own shade rather than a darker copy of the
       page: #060913 inside #0F1322 was barely there, and a field that does not
       read as a field is one nobody taps. */
    --bg-input: #232B52;
    --border-input: #434E86;

    /* Stacking layers. Anything positioned should pick one of these rather
       than inventing a number, so page content can never rise above the
       sticky header the way an open autocomplete list once did. */
    /* Height of the sticky header. Anything that sticks inside the page has to
       park below it, so the offset lives here instead of being guessed twice. */
    --header-height: 4.125rem;
    /* The navigation strip is the brand orange (Dimas, 2026-10-27, SHOW-43). */
    --nav-progress: var(--accent-primary);

    --z-content: 5;      /* in-page positioned elements */
    --z-popover: 50;     /* dropdowns and autocomplete lists */
    --z-chrome: 200;     /* sticky header and bottom navigation */
    --z-modal: 1000;     /* modal overlays */
    --z-notice: 9999;    /* toasts and the pull-to-refresh indicator */
    
    /* List priority colors */
    --color-my-dogs: #EF4444;    /* Coral Red */
    --color-important: #F59E0B;  /* Amber Orange */
    --color-orders: #3B82F6;     /* Electric Blue */
    --color-friends: #10B981;    /* Emerald Green */
    
    /* Typography */
    --font-display: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-body: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    
    /* Effects */
    --radius-sm: 8px;
    --radius-md: 14px;
    --radius-lg: 20px;
    --shadow-premium: 0 10px 30px -10px rgba(0, 0, 0, 0.7);
    --transition-premium: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);

    /* The faintest possible lift off the background: hovered rows, striped
       tables, a secondary button under the cursor. It has to invert with the
       theme -- white at 2% is invisible on a white page, and that is a hover
       state and a table stripe silently disappearing rather than a colour
       being slightly off. */
    --tint-subtle: rgba(255, 255, 255, 0.03);
    --tint-subtle-strong: rgba(255, 255, 255, 0.05);
}

/*
 * The light palette.
 *
 * Only the variables are redefined -- nothing below this block knows which
 * theme it is painted in, which is the whole reason 950-odd rules could be
 * given a second palette without being touched. Written once and applied
 * twice: explicitly when the reader chose light, and through
 * prefers-color-scheme when they chose to follow the device.
 *
 * The accent does not change. It is the brand, it carries enough contrast on
 * both grounds, and an orange that shifted with the theme would read as two
 * different products.
 */
:root[data-theme="light"],
:root[data-theme="system"] {
    --bg-base-rgb: 247, 248, 250;
    --bg-surface-rgb: 255, 255, 255;
    --bg-card-rgb: 255, 255, 255;
    --bg-overlay-rgb: 237, 240, 246;

    --text-primary-rgb: 17, 24, 39;
    --text-secondary-rgb: 75, 85, 99;
    --text-muted-rgb: 107, 114, 128;

    --border-color-rgb: 226, 230, 238;
    --border-highlight-rgb: 203, 210, 224;

    --bg-base: #F7F8FA;
    --bg-surface: #FFFFFF;
    --bg-card: #FFFFFF;
    --bg-overlay: #EDF0F6;

    --text-primary: #111827;
    --text-secondary: #4B5563;
    --text-muted: #6B7280;

    --border-color: #E2E6EE;
    --border-highlight: #CBD2E0;

    --bg-input: #E4E8F1;
    --border-input: #B4BDCF;

    /* The dark shadow was 70% black lifted off a near-black ground, which on
       white is a smudge. Light needs far less of it to read as raised. */
    --shadow-premium: 0 8px 24px -12px rgba(17, 24, 39, 0.18);

    --tint-subtle: rgba(17, 24, 39, 0.035);
    --tint-subtle-strong: rgba(17, 24, 39, 0.06);
}

/* Chosen light, and meant it: this must win even where the device says dark. */
:root[data-theme="light"] {
    color-scheme: light;
}

/* Following the device. The variables above are the light half, so the dark
   half is simply the defaults from :root, put back when the device asks. */
:root[data-theme="system"] {
    color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
    :root[data-theme="system"] {
        --bg-base-rgb: 6, 9, 19;
        --bg-surface-rgb: 15, 19, 34;
        --bg-card-rgb: 20, 26, 46;
        --bg-overlay-rgb: 29, 36, 63;

        --text-primary-rgb: 243, 244, 246;
        --text-secondary-rgb: 156, 163, 175;
        --text-muted-rgb: 107, 114, 128;

        --border-color-rgb: 30, 37, 64;
        --border-highlight-rgb: 42, 51, 91;

        --bg-base: #060913;
        --bg-surface: #0F1322;
        --bg-card: #141A2E;
        --bg-overlay: #1D243F;

        --text-primary: #F3F4F6;
        --text-secondary: #9CA3AF;
        --text-muted: #6B7280;

        --border-color: #1E2540;
        --border-highlight: #2A335B;

        --bg-input: #232B52;
        --border-input: #434E86;

        --shadow-premium: 0 10px 30px -10px rgba(0, 0, 0, 0.7);

        --tint-subtle: rgba(255, 255, 255, 0.03);
        --tint-subtle-strong: rgba(255, 255, 255, 0.05);
    }
}

/* The document itself never scrolls sideways. body alone is not enough: with a
   fixed overlay open, the horizontal scroll a phone offered belonged to the
   root element, which is what made the dashboard slide left and right behind
   an open dialog.

   clip, not hidden: `hidden` makes this element a scroll container, and a
   sticky descendant sticks to that container rather than to the viewport — it
   unstuck the site header the moment it was added. `clip` refuses the scroll
   without creating the container, so the header keeps its perch. */
html {
    overflow-x: clip;
}

/*
 * Interface size.
 *
 * Three sets, chosen in Settings > Appearance and printed on <html> as
 * data-scale. Nothing below this block knows which set it is drawn at: sizes
 * and spacing are written in rem, so moving the root font size moves type and
 * padding together, which is what "a larger interface" has to mean -- type
 * alone grown inside unchanged boxes is a cramped page, not a bigger one.
 *
 * Compact is the original and is exactly 100%: every rem below was converted
 * from the pixel value it already had, so a reader who never opens this
 * setting sees the app unchanged to the pixel.
 *
 * A percentage rather than a pixel size, because the root font size a reader
 * set in their own browser is a preference too, and multiplying it keeps that
 * honoured. The two larger steps are deliberately modest -- roughly an eighth
 * and a quarter -- since a phone at a ringside has a fixed width, and past
 * that a table stops fitting rather than becoming easier to read.
 */
:root,
:root[data-scale="compact"] {
    font-size: 100%;
}

:root[data-scale="medium"] {
    font-size: 112.5%;
}

:root[data-scale="large"] {
    font-size: 125%;
}

/* Base resets */
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

/*input, textarea, select, .btn-premium {*/
/*    box-sizing: border-box;*/
/*}*/

/* The browser hides [hidden] from its own stylesheet, and ANY author `display`
   beats it — so a class like .expo-schedule-pill (display: inline-flex) left
   hidden pills on screen: every show showed "Source changed" while the totals,
   read from the same elements in JS, said zero. Author-level, so it wins. */
[hidden] {
    display: none !important;
}

body {
    background-color: var(--bg-base);
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 0.95rem;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    padding-bottom: 5.625rem;
    /* clip, not hidden, for the same reason as on html above: hidden makes body
       a scroll container and the sticky header then sticks to body instead of
       to the viewport — which is to say it does not stick at all. */
    overflow-x: clip;
    overscroll-behavior-y: none;
}

/* Every link is the brand colour unless a component gives it another
   (Dimas, 2026-10-20). A bare element selector, so any class still wins; and
   an author rule beats the browser's own, so its blue and visited purple —
   which showed on the judge profile — never reach a page. */
a { color: var(--accent-primary); }

/* Header & Branding */
header {
    background-color: rgba(var(--bg-base-rgb), 0.8);
    backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--border-color);
    padding: 0 1.5rem;
    /* Fixed height so --header-height is the truth for sticky offsets below. */
    height: var(--header-height);
    display: flex;
    justify-content: space-between;
    align-items: center;
    position: sticky;
    top: 0;
    z-index: var(--z-chrome);
}

/*
 * The masthead does not take part in the interface size.
 *
 * Everything else in the app is written in rem so that compact, medium and
 * large move type and spacing together -- but the mark, the name beside it and
 * the version under that are the app's signature, not text anybody reads a
 * timetable from. Grown a quarter they crowd out the header without helping
 * anyone, so this corner is pinned in pixels on purpose. The values are the
 * rem they replaced, at the compact root: nothing moves at the default size.
 */
.brand {
    font-family: var(--font-display);
    font-size: 22.4px;
    font-weight: 800;
    letter-spacing: -0.03em;
    color: var(--text-primary);
    display: inline-flex;
    align-items: center;
    gap: 0;
    text-decoration: none;
}

.brand-logo {
    display: block;
    width: 65px;
    height: 65px;
    object-fit: contain;
}

.header-brand {
    display: flex;
    align-items: center;
}

.header-brand-text {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.brand span {
    color: var(--accent-primary);
}

.brand:hover {
    filter: drop-shadow(0 0 8px var(--accent-glow));
}

.clock-panel {
    text-align: right;
    padding-left: 0.4375rem;
    line-height: 1.2;
}

.header-tools {
    align-items: center;
    display: flex;
    gap: 0;
}

.account-avatar {
    align-items: center;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 50%;
    color: var(--text-primary);
    display: flex;
    flex: 0 0 auto;
    justify-content: center;
    height: 40px;
    margin: 0 0 0 10px;
    /* The unread badge sits on the rim and must be allowed out; the photograph
       is cropped by its own radius instead of by the frame's overflow. */
    overflow: visible;
    position: relative;
    width: 40px;
}

.account-avatar svg {
    fill: none;
    height: 19px;
    stroke: currentColor;
    stroke-linecap: round;
    stroke-width: 1.7;
    width: 19px;
}

.account-avatar img {
    border-radius: 50%;
    display: block;
    height: 100%;
    object-fit: cover;
    width: 100%;
}

/* Feedback nobody has opened. Red, on the rim of the avatar, and only ever
   rendered for an administrator — the header does not draw an empty badge and
   wait, because a badge that is sometimes zero is a badge people learn to
   ignore. */
.account-unread {
    align-items: center;
    background: var(--color-my-dogs);
    border: 2px solid var(--bg-surface);
    border-radius: 999px;
    color: #fff;
    display: flex;
    font: 700 .62rem/1 var(--font-display);
    height: 18px;
    justify-content: center;
    min-width: 18px;
    /* em, not px: the chip grows with its own digits when a reader turns the
       interface size up, and the pixel-padding sweep in test_scale_choice
       stays meaningful. */
    padding: 0 0.3em;
    position: absolute;
    right: -4px;
    top: -4px;
}

.account-avatar.has-unread { border-color: rgba(var(--color-my-dogs-rgb), .6); }
/* display: flex above would otherwise beat the hidden attribute: the
   notifications bell beside the avatar is hidden until app.js shows it (DIM-813). */
.account-avatar[hidden] { display: none; }
.account-push-off { color: var(--accent-primary); }
/* On a phone the header has no room for two 16px gaps: the bell and the
   avatar sit 6px apart, or the clock is pushed off the right edge (DIM-813). */
@media (max-width: 520px) { .account-avatar.account-push-off { margin-right: 0; } .account-push-off + .account-avatar { margin-left: 6px; } }

.account-avatar:hover {
    border-color: var(--accent-primary);
    color: var(--accent-primary);
}

.account-avatar:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 2px;
}

.guest-account-links {
    align-items: center;
    display: flex;
    gap: 0.5rem;
}

.guest-account-links a {
    border: 1px solid var(--border-color);
    border-radius: 7px;
    color: var(--text-primary);
    font: 700 .72rem var(--font-display);
    padding: 0.4375rem 0.625rem;
    text-decoration: none;
    text-transform: uppercase;
}

.guest-account-links a:last-child {
    background: var(--accent-primary);
    border-color: var(--accent-primary);
    color: #fff;
}

/* The migration ledger. A list of files where the interesting column is the
   one that says whether it ran, so the state is a coloured word next to the
   name rather than something to work out from a date. */
.migration-list { display: grid; gap: 0; }
.migration-row { align-items: start; border-top: 1px solid var(--border-color); display: grid; gap: 1rem; grid-template-columns: 1fr auto; padding: 0.75rem 0; }
.migration-row:first-child { border-top: 0; }
.migration-name strong { display: block; font: 600 .88rem var(--font-display); overflow-wrap: anywhere; }
.migration-name small { color: var(--text-muted); display: block; font-size: .74rem; margin-top: 2px; }
.migration-status { font-weight: 700; }
.migration-ok .migration-status { color: var(--color-friends); }
.migration-adopted .migration-status { color: var(--text-secondary); }
.migration-pending .migration-status { color: var(--color-important); }
.migration-failed .migration-status { color: var(--color-my-dogs); }
.migration-running .migration-status { color: var(--color-orders); }
.migration-changed { color: var(--color-important); }
.migration-output { margin-top: 6px; }
.migration-output summary { color: var(--text-secondary); cursor: pointer; font-size: .74rem; }
.migration-output pre { background: var(--bg-base); border-radius: var(--radius-sm); font-size: .72rem; margin-top: 6px; overflow-x: auto; padding: 0.625rem; white-space: pre-wrap; }
.migration-row .btn-premium { padding: 0.5rem 1rem; width: auto; }

@media (max-width: 560px) {
    .migration-row { grid-template-columns: 1fr; }
    .migration-row .btn-premium { justify-self: start; }
}

/* "+ Create" at the head of the row of kinds on the Lists page (DIM-775):
   the same chip, in the accent colour, so it reads as the action and not as
   one more kind of list. */
.list-create-btn {
    background: rgba(var(--accent-primary-rgb), .12);
    border-color: var(--accent-primary);
    color: var(--accent-primary);
    cursor: pointer;
}
.list-create-btn:hover { background: var(--accent-primary); color: var(--bg-base); }
.empty-state .list-create-btn { margin-top: 1rem; }

/* The kind switches on the Lists page. Same chips as the dashboard, but they
   start at the left edge here: they are the page's first choice, not a filter
   tucked against the right of something already on screen. */
.list-type-filter { flex-wrap: wrap; justify-content: flex-start; }
.list-choose-hint { color: var(--text-muted); font-size: .85rem; margin: 14px 0; }
/* Pencil and bin on the end of a row of a list. */
.list-item-actions { display: flex; flex: 0 0 auto; gap: 0.5rem; }

.list-pill-show { font-size: .72rem; font-weight: 400; margin-left: auto; opacity: .6; text-align: right; white-space: nowrap; }

/* A list on the Lists page (Dimas, 2026-10-20, DIM-793): the name a size up and
   white, the comment under it in the colour it had, and the list's Change
   menu as a pencil at the right that shows on hover or after a long press. */
.list-pill-wrap { position: relative; }
.list-pill-wrap:hover, .list-pill-wrap:focus-within, .list-pill-wrap.is-holding { z-index: 2; }
.list-pill-wrap .list-pill { -webkit-touch-callout: none; -webkit-user-select: none; padding-right: 3.25rem; user-select: none; }
.list-pill-text { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }
.list-pill-name { color: var(--text-primary); font-size: .95rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list-pill-text .list-pill-show { margin-left: 0; text-align: left; white-space: normal; }
.list-pill-wrap .list-pill-actions { opacity: 0; pointer-events: none; position: absolute; right: 0.5rem; top: 50%; transform: translateY(-50%); transition: opacity .15s ease; }
.list-pill-wrap:hover .list-pill-actions,
.list-pill-wrap:focus-within .list-pill-actions,
.list-pill-wrap.is-holding .list-pill-actions,
.list-pill-actions:has([aria-expanded="true"]) { opacity: 1; pointer-events: auto; }
.list-pill-edit { align-items: center; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 8px; color: var(--text-secondary); cursor: pointer; display: inline-flex; height: 2.25rem; justify-content: center; width: 2.25rem; }
.list-pill-edit:hover { border-color: var(--accent-primary); color: var(--text-primary); }
/* Square: the menu trigger's own width: auto must not stretch it into a pill. */
.list-pill-wrap.is-holding .list-pill-edit { visibility: hidden; } /* a long press shows the menu, not the pencil */
/* The eye beside the pencil (DIM-796): shown with the pencil on hover; on a
   hidden list it stays, shut, and the list is greyed. */
.list-pill-eye-form { margin: 0; opacity: 0; pointer-events: none; position: absolute; right: 3.125rem; top: 50%; transform: translateY(-50%); transition: opacity .15s ease; }
.list-pill-wrap:hover .list-pill-eye-form,
.list-pill-wrap:focus-within .list-pill-eye-form,
.list-pill-wrap.is-hidden-list .list-pill-eye-form { opacity: 1; pointer-events: auto; }
.list-pill-eye { align-items: center; aspect-ratio: 1; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 8px; box-sizing: border-box; color: var(--text-secondary); cursor: pointer; display: inline-flex; height: 2.25rem; justify-content: center; padding: 0; width: 2.25rem; }
.list-pill-eye:hover { border-color: var(--accent-primary); color: var(--text-primary); }
.list-pill-eye .action-icon { height: 1rem; width: 1rem; }
.list-pill-wrap .list-pill { padding-right: 5.5rem; }
.list-pill-wrap.is-hidden-list .list-pill { opacity: .5; }
.list-pill-wrap.is-hidden-list .list-pill-name { color: var(--text-secondary); }

/* No mouse, no pencil (Dimas, 2026-10-20): a tap leaves a phone's :hover and
   :focus-within stuck on the list, which showed it. The long press opens the
   menu, and only the open menu is shown. */
@media (hover: none) {
    .list-pill-wrap .list-pill-edit { visibility: hidden; }
    /* Nor the eye, but on a hidden list, where it says the list is hidden. */
    .list-pill-wrap:not(.is-hidden-list) .list-pill-eye-form { opacity: 0; pointer-events: none; }
    .list-pill-wrap:not(.is-hidden-list) .list-pill { padding-right: 1rem; }
    .list-pill-wrap:hover .list-pill-actions:not(:has([aria-expanded="true"])),
    .list-pill-wrap:focus-within .list-pill-actions:not(:has([aria-expanded="true"])) { opacity: 0; pointer-events: none; }
}
.list-pill-wrap .list-pill-edit { aspect-ratio: 1; box-sizing: border-box; flex: 0 0 auto; height: 2.25rem; min-width: 0; padding: 0; width: 2.25rem; }
.list-pill-edit .action-icon { height: 1rem; width: 1rem; }
.list-pill-actions .bulk-actions-menu form { margin: 0; }
.list-pill-actions a.bulk-menu-item { color: var(--text-primary); text-decoration: none; }
.list-pill-actions .bulk-actions-menu form .bulk-menu-item { width: 100%; }
.schedule-list-filter { flex-wrap: wrap; margin-bottom: 12px; }
.schedule-list-filter-note { align-self: center; color: var(--accent-primary); font: 700 .72rem var(--font-display); letter-spacing: .04em; text-transform: uppercase; }

/* Translations. The index is a phone book: a code per line, a column per
   language, and a blank column where a translation is missing -- that gap is
   the whole point of the page, so it is spotted without reading anything. */
.translation-search { align-items: stretch; display: flex; gap: 0.625rem; margin-bottom: 10px; max-width: 560px; }
.translation-search .input-field { flex: 1 1 auto; margin: 0; min-width: 0; }
/* .btn-premium is a full-width block by default, which on one row with a field
   eats the field. Beside an input it is only as wide as its own word. */
.translation-search .btn-premium { flex: 0 0 auto; padding: 0.75rem 1.375rem; white-space: nowrap; width: auto; }
.translation-index { margin-top: 24px; }
.translation-letter { display: grid; gap: 0 1.5rem; grid-template-columns: 56px 1fr; margin-bottom: 18px; }
/* The letter follows its own group down and stops at its end, so you always
   know which letter you are inside of. align-self keeps it its own height --
   a stretched grid item fills its area and has nowhere to stick to -- and the
   grid area is the group, which is what confines it to its own block.
   --header-height is the fixed header it must park under; it is a token
   precisely so this offset is not guessed a second time. */
.translation-letter h2 {
    align-self: start;
    color: var(--text-muted);
    font: 700 2rem var(--font-display);
    margin: 0;
    position: sticky;
    text-align: center;
    top: calc(var(--header-height) + 12px);
    z-index: var(--z-content);
}
.translation-rows { display: grid; }
.translation-row { align-items: baseline; border-radius: var(--radius-sm); display: grid; gap: 1rem; grid-template-columns: 1fr auto; padding: 0.375rem 0.5rem; text-decoration: none; }
.translation-row:hover { background: var(--bg-overlay); }
.translation-name { display: grid; gap: 0.0625rem; min-width: 0; }
.translation-text { color: var(--accent-primary); font-size: .92rem; overflow-wrap: anywhere; }
.translation-text.untranslated { color: var(--color-important); font-style: italic; }
.translation-code { color: var(--text-muted); font-size: .7rem; letter-spacing: .02em; overflow-wrap: anywhere; }
.translation-editing-code { color: var(--text-muted); font-size: .78rem; margin: -8px 0 18px; }
.translation-langs { display: grid; gap: 0.25rem; grid-template-columns: repeat(5, 28px); }
.translation-lang-mark { color: var(--text-secondary); font-size: .78rem; text-align: center; }
.translation-lang-mark.missing { border-bottom: 1px solid rgba(var(--color-important-rgb),.35); }

.translation-editor { display: grid; gap: 0.75rem; }
.translation-field { align-items: start; display: grid; gap: 0.625rem; grid-template-columns: 32px 1fr; }
.translation-field .input-field { margin: 0; }
.translation-lang { color: var(--text-muted); font: 700 .72rem var(--font-display); padding-top: 0.625rem; }
.translation-field.missing .input-field { border-color: rgba(var(--color-important-rgb),.5); }
.translation-field.missing .translation-lang { color: var(--color-important); }
.translation-flag { align-items: start; display: grid; gap: 0.625rem; grid-template-columns: 18px 1fr; }
.translation-flag small { color: var(--text-muted); display: block; font-size: .76rem; }
.translation-delete { align-items: center; display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 18px; }
.translation-delete .settings-intro { flex: 1; margin: 0; min-width: 240px; }

@media (max-width: 560px) {
    .translation-letter { grid-template-columns: 34px 1fr; gap: 0 0.625rem; }
    .translation-row { grid-template-columns: 1fr; gap: 0.125rem; }
}

.language-choices { display: flex; flex-wrap: wrap; gap: 0.625rem; margin: 18px 0; }
.language-choice { align-items: center; background: var(--bg-base); border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-secondary); cursor: pointer; display: flex; font: inherit; gap: 0.625rem; padding: 0.75rem 1rem; transition: var(--transition-premium); }
.language-choice:hover { border-color: var(--accent-primary); color: var(--text-primary); }
.language-choice.active { border-color: var(--accent-primary); color: var(--text-primary); }
.language-choice-code { color: var(--accent-primary); font: 800 .72rem var(--font-display); }
.language-choice:focus-visible { outline: 2px solid var(--accent-primary); outline-offset: 2px; }

/* Theme picker. Same shape as the language choices, plus a swatch: the three
   options differ in how they look, so showing it beats describing it. The
   swatches are painted in literal colours on purpose -- a dark swatch has to
   stay dark while the page around it is light, or it illustrates nothing. */
.theme-choices { display: flex; flex-direction: column; gap: 0.625rem; margin: 18px 0; }
.theme-choice { align-items: center; background: var(--bg-base); border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-secondary); cursor: pointer; display: flex; font: inherit; gap: 0.75rem; padding: 0.75rem 1rem; text-align: left; transition: var(--transition-premium); width: 100%; }
.theme-choice:hover { border-color: var(--accent-primary); color: var(--text-primary); }
.theme-choice.active { border-color: var(--accent-primary); color: var(--text-primary); }
.theme-choice:focus-visible { outline: 2px solid var(--accent-primary); outline-offset: 2px; }
.theme-choice-text { display: flex; flex-direction: column; gap: 0.125rem; }
.theme-choice-text strong { color: var(--text-primary); font: 700 .9rem var(--font-display); }
.theme-choice-text small { color: var(--text-muted); font-size: .76rem; }
.theme-choice-swatch { border: 1px solid var(--border-highlight); border-radius: 50%; flex: 0 0 auto; height: 26px; width: 26px; }
/* Settings → Notifications: one table, the notice on the left and a column of
   toggles each for Pop-up and Email (DIM-813, Dimas 2026-10-21). */
.notify-table { display: flex; flex-direction: column; gap: 0.5rem; margin: 18px 0 4px; }
.notify-row { align-items: center; display: grid; gap: 0.75rem; grid-template-columns: minmax(0, 1fr) 72px 72px; }
.notify-row:not(.notify-head) { background: var(--bg-base); border: 1px solid var(--border-color); border-radius: var(--radius-sm); padding: 0.75rem 0.5rem 0.75rem 1rem; }
.notify-head { color: var(--text-muted); font-size: .68rem; font-weight: 700; letter-spacing: .02em; line-height: 1.2; padding: 0 0.5rem 0 1rem; text-transform: uppercase; }
/* A column title wider than its column wraps onto a second line instead of
   running into its neighbour, as the Russian "Всплывающие" did (DIM-813). */
.notify-head span, .notify-cell { display: flex; justify-content: center; min-width: 0; text-align: center; }
.notify-minutes { background: var(--bg-elevated, var(--bg-base)); border: 1px solid var(--border-color); border-radius: 6px; color: var(--text-primary); font: inherit; font-weight: 700; margin: 0 .15rem; padding: .06em .12em; text-align: center; width: 3.2em; }
.notify-switch { appearance: none; background: var(--border-color); border-radius: 999px; cursor: pointer; flex: 0 0 auto; height: 24px; margin: 0; position: relative; transition: background .2s; width: 42px; }
.notify-switch::before { background: #fff; border-radius: 50%; content: ""; height: 18px; left: 3px; position: absolute; top: 3px; transition: transform .2s; width: 18px; }
.notify-switch:checked { background: var(--accent-primary); }
.notify-switch:checked::before { transform: translateX(18px); }
.notify-switch:focus-visible { outline: 2px solid var(--accent-primary); outline-offset: 2px; }
.push-device { align-items: center; display: flex; flex-wrap: wrap; gap: 0.75rem; margin: 12px 0 4px; }
.push-device-state { margin: 0; }
.notify-saving { background: var(--bg-surface); border: 1px solid var(--border-color); border-radius: 999px; bottom: calc(84px + env(safe-area-inset-bottom)); color: var(--text-primary); font-size: .85rem; left: 50%; margin: 0; padding: 0.45rem 1rem; position: fixed; transform: translateX(-50%); z-index: 50; }
.theme-swatch-dark { background: #0F1322; }
.theme-swatch-light { background: #F7F8FA; }
.theme-swatch-system { background: linear-gradient(135deg, #0F1322 0 50%, #F7F8FA 50% 100%); }

/* The size choices reuse the theme rows; the swatch is replaced by an "Aa"
   drawn at the size that choice actually gives, so the row is a sample rather
   than a description of one. Sizes in em against the row's own text, so the
   samples stay in the same proportion whichever set is currently on. */
.scale-choice-sample { align-items: center; color: var(--text-primary); display: flex; flex: 0 0 auto; font-family: var(--font-display); font-weight: 700; justify-content: center; line-height: 1; width: 1.75rem; }
.scale-sample-compact { font-size: .82rem; }
.scale-sample-medium { font-size: 1rem; }
.scale-sample-large { font-size: 1.2rem; }

/* Language switcher. A <details> rather than a scripted menu: it belongs in the
   header for a guest who has not loaded anything yet, and the five entries are
   plain links carrying ?lang, so it works with no JavaScript at all. */
.lang-switch {
    position: relative;
}

.lang-switch > summary {
    border: 1px solid var(--border-color);
    border-radius: 7px;
    color: var(--text-secondary);
    cursor: pointer;
    font: 700 .72rem var(--font-display);
    list-style: none;
    margin: 0 8px;
    padding: 0.4375rem 0.5625rem;
    user-select: none;
}

.lang-switch > summary::-webkit-details-marker { display: none; }

.lang-switch > summary:hover,
.lang-switch[open] > summary {
    border-color: var(--border-highlight);
    color: var(--text-primary);
}

.lang-switch > summary:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 2px;
}

.lang-switch-menu {
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, .4);
    display: flex;
    flex-direction: column;
    min-width: 160px;
    overflow: hidden;
    position: absolute;
    right: 0;
    top: calc(100% + 6px);
    z-index: var(--z-popover);
}

.lang-switch-menu a {
    color: var(--text-secondary);
    font-size: .85rem;
    padding: 0.625rem 0.875rem;
    text-decoration: none;
    white-space: nowrap;
}

.lang-switch-menu a:hover {
    background: var(--bg-overlay);
    color: var(--text-primary);
}

.lang-switch-menu a.active {
    color: var(--accent-primary);
    font-weight: 600;
}

.clock-time {
    font-family: var(--font-display);
    font-size: 1.3rem;
    font-weight: 700;
    color: var(--accent-primary);
    letter-spacing: -0.02em;
}

.blink-colon {
    animation: blink-colon 1s step-end infinite;
}

@keyframes blink-colon {
    50% { opacity: 0; }
}

.clock-date {
    font-size: 0.75rem;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* Main Container */
.container {
    max-width: 1200px;
    width: 100%;
    margin: 0 auto;
    padding: 1.25rem;
    /* Clear the fixed bottom nav so the last card is never trapped under it. */
    padding-bottom: calc(5rem + env(safe-area-inset-bottom, 0px));
}
@media (max-width: 500px) {
    .container {
        padding: 0.625rem;
        padding-bottom: calc(4.625rem + env(safe-area-inset-bottom, 0px));
    }
    header {
        padding: 0 0.625rem 0 0.125rem;
    }
}



/* Section Header Typography */
.section-header,
.settings-group-title {
    font-family: var(--font-display);
    font-size: 1.15rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    line-height: 1.2;
    color: var(--text-secondary);
    margin: 32px 0 16px 0;
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.section-header::after,
.settings-group-title::after {
    content: '';
    flex: 1;
    height: 1px;
    background-color: var(--border-color);
}

/* Active Show Pill */
.active-show-bar {
    background: linear-gradient(90deg, var(--bg-surface) 0%, var(--bg-card) 100%);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    display: flex;
    flex-direction: column;
    margin-bottom: 24px;
    box-shadow: var(--shadow-premium);
    overflow: hidden;
}

.active-show-header {
    padding: 0.875rem 1.25rem;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}

/* The dashboard pill and a row of the shows list are the same card: a mark, a
   name, a venue, a tag. They were two families of class saying it twice, which
   is why the mark and the pin had to be added to each of them separately and
   why line-height: 1 landed on one of the two names. The pill keeps only what
   is really its own -- the bar, the header row, the countdown and the day
   buttons -- and everything inside it is .show-card-*.

   The info block still has to be the one that grows: the header is
   space-between, and without this the name and the countdown drift apart. */
.active-show-header .show-card-info { flex: 1 1 auto; }

.active-show-countdown {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    text-align: right;
    white-space: nowrap;
    line-height: 1.2;
}

.active-show-countdown-value {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.4rem;
    color: var(--accent-primary);
}

.active-show-countdown-label {
    font-weight: 400;
    font-size: 1rem;
    color: var(--text-secondary);
}

/* The "now" tag in the countdown's place while the rings run. The badge the
   ring rows wear, a size up: it stands alone on the right, not beside a name.
   Two classes, because .schedule-now-badge is declared further down. */
.schedule-now-badge.active-show-now {
    margin-left: 0;
    font-size: 0.8rem;
    padding: 0.25rem 0.5rem;
}

.active-show-dates {
    display: flex;
    width: 100%;
    border-top: 1px solid var(--border-color);
}

.active-show-date-btn {
    flex: 1;
    text-align: center;
    padding: 0.625rem;
    font-size: 0.85rem;
    font-family: var(--font-display);
    text-decoration: none;
    font-weight: 700;
    color: var(--text-secondary);
    background-color: var(--bg-overlay);
    border-right: 1px solid var(--border-color);
    transition: var(--transition-premium);
}

.active-show-date-btn:last-child {
    border-right: none;
}

.active-show-date-btn:hover {
    background-color: var(--bg-surface);
    color: var(--text-primary);
}

.active-show-date-btn.active {
    background-color: var(--accent-primary);
    color: white;
}

/* A show whose ring schedule has not been imported yet. The name is a span
   rather than a link on this one, so there is nothing to hover and nothing
   to open -- the timetable behind it would be empty. */
.active-show-bar-unscheduled {
    opacity: 0.65;
}

/* The agreement at sign-up, and the cookie question in the welcome dialog. Both
   are a paragraph the reader has to be able to read before answering, so the
   control sits beside the text rather than above a wall of it. */
.auth-agree { align-items: flex-start; display: flex; font-weight: 400; gap: 0.5rem; line-height: 1.35; }
/* .settings-form input is display:block;width:100%, which a checkbox has no
   business inheriting: at full width it pushed the sentence beside it clean off
   the right of the screen. Overridden by element, not by class, so a checkbox
   added to this label later behaves the same. */
.auth-agree input[type="checkbox"] { flex: 0 0 auto; margin: 2px 0 0; width: auto; }
.auth-agree span { flex: 1 1 auto; font-size: .84rem; min-width: 0; }
.auth-agree a { color: var(--accent-primary); }
/* Belongs to the field above it, so it takes back most of the form's 1rem gap. */
.settings-form .auth-field-hint { margin-top: -0.625rem; }

/* The cookie question, on every page. It sits above the bottom navigation
   rather than over the header — the header carries the brand, the clock and the
   account — and above the raised dashboard circle, the same clearance the
   offline banner takes. Not fixed to the very bottom, because that is where the
   navigation is and a reader's thumb is already there. */
.consent-bar {
    background: var(--bg-card);
    border-top: 1px solid var(--border-color);
    bottom: calc(4.75rem + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 -12px 32px rgba(0,0,0,.45);
    left: 0;
    margin: 0 auto;
    max-width: 800px;
    padding: 0.875rem 1rem;
    position: fixed;
    right: 0;
    z-index: var(--z-notice);
}

.consent-bar[hidden] { display: none !important; }
/* The same question, asked again on the cookies page so an answer can be taken
   back. Hidden until the client has read the stored answer. */
.consent-choice { border-top: 1px solid var(--border-color); margin-top: 14px; padding-top: 0.875rem; }
.consent-choice[hidden] { display: none !important; }
.consent-choice-state { color: var(--text-primary); font: 600 .84rem var(--font-display); margin: 0; }
.consent-bar-text { color: var(--text-secondary); font-size: .82rem; line-height: 1.4; margin: 0; }
.consent-bar a { color: var(--accent-primary); }
.consent-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 12px; }
.consent-actions .btn-premium { flex: 1 1 auto; width: auto; }

@media (min-width: 560px) {
    .consent-bar { border: 1px solid var(--border-color); border-radius: var(--radius-md); left: 16px; right: 16px; }
}

.info-subheading { color: var(--text-primary); font: 700 .92rem var(--font-display); margin: 16px 0 6px; }

/* List Selector: one list per line, top to bottom (Dimas, 2026-10-19,
   DIM-775). It was a row that scrolled sideways, and a list past the edge of
   the screen was a list nobody knew they had. */
.list-pills {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin: 1rem 0 1.25rem;
}

.list-pill {
    padding: 0.75rem 1rem;
    border-radius: var(--radius-sm);
    font-size: 0.85rem;
    font-family: var(--font-display);
    font-weight: 600;
    text-decoration: none;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background-color: var(--bg-surface);
    color: var(--text-secondary);
    border: 1px solid var(--border-color);
    transition: var(--transition-premium);
    min-width: 0;
}

.list-pill:hover {
    color: var(--text-primary);
    border-color: var(--border-highlight);
}

.list-pill.active {
    color: var(--text-primary);
    background-color: var(--bg-card);
    border-color: var(--accent-primary);
}

.list-pill-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex: 0 0 auto;
}

/* Cards & Layout */
.card-premium {
    background-color: var(--bg-surface);
    /*border: 1px solid var(--border-color);*/
    border-radius: var(--radius-md);
    padding: 0.75rem;
    margin-bottom: 10px;
    box-shadow: var(--shadow-premium);
    transition: var(--transition-premium);
}

/* Hover belongs to a pointer that can hover. On iOS the first tap on an
   element with a hover style is spent producing that hover and the click only
   lands on the second tap, which is why an admin had to tap a ring row twice to
   open the time picker. Touch never enters the hover state now, so the first
   tap is the click. */
@media (hover: hover) {
    .card-premium:hover {
        border-color: var(--border-highlight);
        transform: translateY(-2px);
    }
}

/* Settings subpages */
.settings-group-title:first-of-type { margin-top: 8px; }
/* Who is signed in, and the way out: the header's old account panel, given a
   line of its own at the top of Settings. */
.settings-account { align-items: center; background: var(--bg-surface); border: 1px solid var(--border-color); border-radius: var(--radius-md); display: flex; gap: 1rem; justify-content: space-between; margin-bottom: 0.5rem; padding: 0.875rem 1rem; }
.settings-account-who { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }
.settings-account-who strong { color: var(--text-primary); font: 700 1rem var(--font-display); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.settings-account-who small { color: var(--text-muted); font-size: .7rem; letter-spacing: .05em; text-transform: uppercase; }
.settings-account .btn-premium { flex: 0 0 auto; padding: 0.5rem 1rem; width: auto; }
.settings-account .settings-signout { border-color: var(--color-my-dogs); }
.settings-account .settings-signout:hover { background-color: rgba(var(--color-my-dogs-rgb),.12); }
.settings-menu { display: grid; gap: 0.625rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.settings-menu-item { align-items: center; background: var(--bg-surface); border: 1px solid var(--border-color); border-radius: var(--radius-md); color: var(--text-primary); display: grid; gap: 0.875rem; grid-template-columns: 42px 1fr auto; padding: 0.5rem 0.5rem; text-decoration: none; transition: var(--transition-premium); }
.settings-menu-item:hover { border-color: var(--accent-primary); transform: translateY(-2px); }
.settings-menu-item:focus-visible, .btn-premium:focus-visible, .settings-back:focus-visible { outline: 2px solid var(--accent-primary); outline-offset: 2px; }
.settings-menu-mark { align-items: center; background: rgba(var(--accent-primary-rgb),.12); border: 1px solid rgba(var(--accent-primary-rgb),.25); border-radius: 50%; color: var(--accent-primary); display: flex; flex: 0 0 42px; height: 42px; justify-content: center; width: 42px; }
/* A drawing rather than the initial of the row's English title, which said
   nothing in the other four languages and collided with itself in English. */
.settings-menu-icon { display: block; height: 20px; width: 20px; }
.settings-menu-item strong { display: block; font: 700 .95rem var(--font-display); }
.settings-menu-item small { color: var(--text-muted); display: block; font-size: .75rem; margin-top: 3px; }
.settings-menu-arrow { color: var(--text-muted); font-size: 1.1rem; transition: transform .2s ease; }
.settings-menu-item:hover .settings-menu-arrow { color: var(--accent-primary); transform: translateX(3px); }
/* A way out of anywhere the bottom navigation does not reach. Rendered once, by
   the header, at the top of the container -- it used to be written by hand on
   seventeen pages, at the bottom of most of them, and was missing entirely from
   a dozen others. */
.settings-back { align-items: center; color: var(--text-secondary); display: inline-flex; font: 700 .78rem var(--font-display); gap: 0.25rem; margin: 2px 0 14px; text-decoration: none; }
.settings-back-icon { height: 15px; width: 15px; }
.settings-back:hover { color: var(--accent-primary); }
.settings-intro { color: var(--text-secondary); margin-bottom: 20px; }
.settings-form { display: grid; gap: 1rem; }
.settings-form label { color: var(--text-primary); font-family: var(--font-display); font-weight: 600; }
.settings-form small { color: var(--text-muted); display: block; font-family: var(--font-body); font-size: .76rem; font-weight: 400; }
.settings-form input, .settings-form select { background: var(--bg-input); border: 1px solid var(--border-input); border-radius: var(--radius-sm); color: var(--text-primary); display: block; font: inherit; margin-top: 6px; padding: 0.625rem 0.75rem; width: 100%; }
.settings-form input:focus, .settings-form select:focus { border-color: var(--accent-primary); outline: none; }
.settings-form .btn-premium { justify-self: start; margin-top: 4px; }
.avatar-field { align-items: center; display: grid; gap: 0.875rem; grid-template-columns: 64px 1fr; }
.avatar-preview-wrap { border-radius: 50%; cursor: pointer; display: block; height: 64px; transition: var(--transition-premium); width: 64px; }
.avatar-preview-wrap:hover { box-shadow: 0 0 0 3px rgba(var(--accent-primary-rgb), .35); }
.avatar-controls { display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; }
.avatar-title { color: var(--text-primary); font-family: var(--font-display); font-weight: 600; }
.settings-form .avatar-pick { cursor: pointer; font-size: .78rem; padding: 0.5rem 0.875rem; width: auto; }
/* The picker opens from the photo or the button; the field itself stays out
   of sight but reachable, so the keyboard still tabs to it. */
.settings-form .avatar-file-input { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; white-space: nowrap; width: 1px; }
.avatar-controls:focus-within .avatar-pick { outline: 2px solid var(--accent-primary); outline-offset: 2px; }
.profile-avatar { background: var(--bg-base); border: 1px solid var(--border-highlight); border-radius: 50%; display: block; height: 64px; object-fit: cover; width: 64px; }
.profile-avatar-placeholder { align-items: center; color: var(--accent-primary); display: flex; font: 800 1.35rem var(--font-display); justify-content: center; }
.avatar-crop-modal { max-width: 420px; }
.avatar-crop-modal .modal-header small { color: var(--text-muted); display: block; font-size: .73rem; margin-top: 3px; }
.avatar-crop-body { align-items: center; display: flex; flex-direction: column; }
.avatar-crop-stage { background: #050812; cursor: grab; height: min(300px, calc(100vw - 80px)); overflow: hidden; position: relative; touch-action: none; user-select: none; width: min(300px, calc(100vw - 80px)); }
.avatar-crop-stage.dragging { cursor: grabbing; }
.avatar-crop-stage > img { max-width: none; pointer-events: none; position: absolute; user-select: none; }
.avatar-crop-shade { border: 2px solid rgba(255,255,255,.9); border-radius: 50%; box-shadow: 0 0 0 999px rgba(var(--bg-base-rgb),.68), inset 0 0 0 1px rgba(var(--bg-base-rgb),.35); inset: 0; margin: 8px; pointer-events: none; position: absolute; }
.avatar-zoom-label { color: var(--text-secondary); font: 700 .75rem var(--font-display); margin-top: 18px; width: 100%; }
.avatar-zoom-label input { accent-color: var(--accent-primary); display: block; margin-top: 8px; width: 100%; }
.avatar-crop-actions { display: flex; gap: 0.5rem; margin-top: 20px; width: 100%; }
.avatar-crop-actions .btn-premium { flex: 1; font-size: .76rem; padding: 0.625rem 0.75rem; }
.email-status { border-radius: 20px; float: right; font: 700 .66rem var(--font-display); padding: 0.1875rem 0.5rem; }
.email-status-verified { background: rgba(var(--color-friends-rgb),.12); color: var(--color-friends); }
.email-status-pending { background: rgba(var(--color-important-rgb),.1); color: var(--color-important); }
.resend-verification { border-top: 1px solid var(--border-color); margin-top: 18px; padding-top: 0.875rem; }
.resend-verification button { background: none; border: 0; color: var(--accent-primary); cursor: pointer; font: 700 .78rem var(--font-display); padding: 0; }
.verified-copy { color: var(--color-friends) !important; }
.pending-copy { color: var(--color-important) !important; }
.auth-primary-link { box-sizing: border-box; display: block; margin-top: 18px; text-align: center; text-decoration: none; }
.settings-card-title { font-family: var(--font-display); font-size: 1.1rem; font-weight: 700; margin-bottom: 16px; }
.settings-data { color: var(--text-secondary); display: grid; gap: 0.5rem 1rem; grid-template-columns: 100px 1fr; }
.settings-data strong { color: var(--text-primary); }
.status-ok, .status-error { border-radius: 20px; display: inline-block; font-size: .78rem; margin-left: 8px; padding: 0.125rem 0.5rem; }
.status-ok { background: rgba(var(--color-friends-rgb),.12); color: var(--color-friends); }
.status-error { background: rgba(var(--color-my-dogs-rgb),.12); color: var(--color-my-dogs); }
.table-status-list { margin-bottom: 20px; }
.table-status-list > div { border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; padding: 0.5625rem 0; }
.settings-warning, .settings-success { border-radius: var(--radius-sm); font-size: .85rem; margin-bottom: 16px; padding: 0.75rem; }
.settings-warning { background: rgba(var(--color-important-rgb),.08); color: var(--color-important); }
.settings-success { background: rgba(var(--color-friends-rgb),.08); color: var(--color-friends); }
.debug-mode-form { border-bottom: 1px solid var(--border-color); margin-bottom: 18px; padding-bottom: 1.125rem; }
.debug-mode-switch { align-items: center; cursor: pointer; display: flex; gap: 1rem; justify-content: space-between; }
.debug-mode-switch > span { min-width: 0; }
.debug-mode-switch strong, .debug-mode-switch small { display: block; }
.debug-mode-switch strong { color: var(--text-primary); font: 700 .95rem var(--font-display); }
.debug-mode-switch small { color: var(--text-muted); font-size: .75rem; margin-top: 3px; }
.debug-mode-switch input { height: 1px; opacity: 0; position: absolute; width: 1px; }
.debug-mode-switch i { background: var(--bg-base); border: 1px solid var(--border-highlight); border-radius: 20px; flex: 0 0 auto; height: 26px; position: relative; transition: var(--transition-premium); width: 46px; }
.debug-mode-switch i::after { background: var(--text-muted); border-radius: 50%; content: ""; height: 18px; left: 3px; position: absolute; top: 3px; transition: var(--transition-premium); width: 18px; }
.debug-mode-switch input:checked + i { background: rgba(var(--accent-primary-rgb),.2); border-color: var(--accent-primary); }
.debug-mode-switch input:checked + i::after { background: var(--accent-primary); transform: translateX(20px); }
.debug-mode-switch input:focus-visible + i { outline: 2px solid var(--accent-primary); outline-offset: 2px; }
.debug-clock-status { background: rgba(var(--color-important-rgb),.08); border: 1px solid rgba(var(--color-important-rgb),.22); border-radius: var(--radius-sm); color: var(--color-important); margin-bottom: 18px; padding: 0.875rem; }
.debug-clock-status strong, .debug-clock-status span { display: block; }
.debug-clock-status span { font-size: .82rem; margin-top: 3px; }
.debug-clock-actions { display: flex; flex-wrap: wrap; gap: .75rem; }
.debug-clock-actions .btn-premium { flex: 1 1 10rem; }
.debug-clock-reset { border-top: 1px solid var(--border-color); margin-top: 18px; padding-top: 1.125rem; }
/* Settings → Profiler: hours, threshold and sample are short numbers, one row of three (SHOW-15).
   align-items: end keeps the inputs on one line when a label wraps to two. */
.profiler-fields { align-items: end; display: grid; gap: 1rem; grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 600px) { .profiler-fields { grid-template-columns: 1fr; } }
/* Beside the mark, and pinned with it: see .brand above. */
.debug-clock-tag {
    background: rgba(var(--color-important-rgb), 0.2);
    border: 1px solid rgba(var(--color-important-rgb), 0.4);
    color: var(--color-important);
    padding: 3px 6px;
    border-radius: var(--radius-sm);
    font-size: 16px;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: 12px;
    transition: background 0.2s;
}
.debug-clock-tag:hover {
    background: rgba(var(--color-important-rgb), 0.3);
}
.benefit-banner { align-items: center; background: linear-gradient(110deg, rgba(var(--accent-primary-rgb),.15), var(--bg-surface)); border: 1px solid rgba(var(--accent-primary-rgb),.35); border-radius: var(--radius-md); display: flex; gap: 1.25rem; justify-content: space-between; margin: 16px 0 24px; padding: 1.25rem; }
.benefit-banner strong { color: var(--text-primary); display: block; font: 700 1.05rem var(--font-display); }
.benefit-banner span { color: var(--text-secondary); display: block; font-size: .82rem; margin-top: 2px; }
.benefit-actions { display: flex; flex: 0 0 auto; gap: 0.5rem; }
.benefit-actions .btn-premium { font-size: .72rem; padding: 0.5625rem 0.75rem; text-decoration: none; width: auto; }
.users-layout { display: grid; gap: 1rem; }
.settings-section-bar { align-items: center; display: flex; justify-content: space-between; margin-bottom: 12px; }
.section-header-group { display: flex; flex-direction: column; gap: 0.2rem; }
.settings-section-bar .section-header { margin: 0; }
.settings-section-bar .btn-premium { font-size: .75rem; padding: 0.5625rem 0.8125rem; width: auto; }
.directory-tools { align-items: center; display: flex; gap: 0.5rem; }
/* Two buttons share the right edge of a section bar, so they shrink to fit. */
.btn-compact { font-size: .7rem !important; padding: 0.4375rem 0.6875rem !important; white-space: nowrap; }
/* Stop stands beside the menu rather than inside it, and is only there at all
   while a run is going. */
.breed-toolbar { display: flex; align-items: center; gap: 0.5rem; }
.breed-toolbar > [hidden] { display: none; }
.directory-count { color: var(--text-muted); font: 700 .72rem var(--font-display); text-transform: uppercase; }
.judges-directory { display: grid; gap: 0.75rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.judge-card { background: var(--bg-surface); border: 1px solid var(--border-color); border-radius: var(--radius-md); box-shadow: var(--shadow-premium); overflow: hidden; }
.judge-card-heading { align-items: center; display: flex; gap: 0.75rem; padding: 1rem; }
.judge-monogram { align-items: center; background: rgba(var(--accent-primary-rgb),.12); border: 1px solid rgba(var(--accent-primary-rgb),.25); border-radius: 50%; color: var(--accent-primary); display: flex; flex: 0 0 auto; font: 800 .9rem var(--font-display); height: 42px; justify-content: center; width: 42px; }
.judge-photo { border: 1px solid var(--border-color); border-radius: 50%; flex: 0 0 auto; height: 42px; object-fit: cover; width: 42px; }
.judge-card-identity { flex: 1 1 auto; min-width: 0; }
.judge-card h2 { color: var(--text-primary); font: 700 .95rem var(--font-display); margin: 0; }
.judge-name-link { color: inherit; text-decoration: none; }
.judge-name-link:hover { color: var(--accent-primary); }
.judge-name-link:focus-visible { border-radius: 3px; outline: 2px solid var(--accent-primary); outline-offset: 3px; }
.judge-card-heading p { color: var(--text-muted); font-size: .73rem; margin-top: 3px; }
.judge-card-controls { align-items: center; display: flex; gap: 0.375rem; opacity: 0; pointer-events: none; transform: translateX(5px); transition: opacity .18s ease, transform .18s ease; }
.judge-card:hover .judge-card-controls, .judge-card:focus-within .judge-card-controls { opacity: 1; pointer-events: auto; transform: translateX(0); }
.judge-card-controls form { margin: 0; }
.judge-card-controls .btn-premium { font-size: .68rem; padding: 0.4375rem 0.5rem; text-decoration: none; width: auto; }
.judge-show-list { border-top: 1px solid var(--border-color); display: grid; }
.judge-show-list > p { color: var(--text-muted); font-size: .75rem; padding: 0.75rem; }
.judge-show-list a { align-items: center; color: var(--text-secondary); display: flex; font-size: .78rem; gap: 0.75rem; justify-content: space-between; padding: 0.625rem 0.75rem; text-decoration: none; }
.judge-show-list a + a { border-top: 1px solid rgba(var(--border-color-rgb),.7); }
.judge-show-list a:hover { background: var(--bg-card); color: var(--text-primary); }
.judge-show-list strong { font-weight: 600; }
.judge-show-list span { color: var(--text-muted); flex: 0 0 auto; font-size: .7rem; }
.judge-profile-heading { align-items: center; display: flex; gap: 0.875rem; margin-bottom: 18px; }
.judge-profile-heading .judge-monogram { height: 52px; width: 52px; }
.judge-profile-heading .judge-photo { height: 52px; width: 52px; }
.judge-profile-heading form { margin: 0; }
.judge-show-list > div { align-items: center; color: var(--text-secondary); display: flex; font-size: .78rem; gap: 0.75rem; justify-content: space-between; padding: 0.625rem 0.75rem; }
.judge-show-list > div + div { border-top: 1px solid rgba(var(--border-color-rgb),.7); }
.judge-profile-heading .section-header { margin: 0; }
.judge-profile-heading p { color: var(--text-muted); font-size: .78rem; margin-top: 4px; }
.judge-edit-layout { align-items: start; display: grid; gap: 1rem; grid-template-columns: minmax(0, 1fr) minmax(280px, .85fr); }
.judge-edit-layout .card-premium { margin-bottom: 0; }
/* Edge to edge inside the card: the negative margin is the card's own padding
   (.card-premium, 0.75rem), or the rules stick out past its sides. */
.judge-history-card .judge-show-list { margin: 0 -0.75rem -0.75rem; }
.judge-fci-facts { display: grid; font-size: .8rem; gap: 0.375rem 1rem; grid-template-columns: max-content minmax(0, 1fr); margin: 0.75rem 0 0; }
.judge-fci-facts dt { color: var(--text-muted); }
.judge-fci-facts dd { margin: 0; }
.judge-fci-groups { border-top: 1px solid var(--border-color); display: grid; font-size: .8rem; margin: 0.75rem -0.75rem -0.75rem; }
.judge-fci-group { border-bottom: 1px solid rgba(var(--border-color-rgb),.7); padding: 0.625rem 0.75rem; }
.judge-fci-group:last-child { border-bottom: 0; }
div.judge-fci-group, .judge-fci-group summary { align-items: baseline; display: flex; gap: 0.75rem; justify-content: space-between; }
.judge-fci-group summary { cursor: pointer; list-style: none; }
.judge-fci-group summary::-webkit-details-marker { display: none; }
.judge-fci-group > span, .judge-fci-group summary > span { color: var(--text-muted); flex: 0 0 auto; }
.judge-fci-group-title { align-items: baseline; display: flex; gap: 0.5rem; }
.judge-fci-group ul { columns: 2 14rem; margin: 0.5rem 0 0; padding-left: 1rem; }
.judge-fci-group small { color: var(--text-muted); }
.users-card { overflow: hidden; }
.users-table-wrap { overflow-x: auto; }
.users-table { border-collapse: collapse; min-width: 520px; width: 100%; }
.users-table th, .users-table td { border-bottom: 1px solid var(--border-color); padding: 0.6875rem 0.5rem; text-align: left; }
.users-table th { color: var(--text-muted); font: 700 .7rem var(--font-display); text-transform: uppercase; }
.users-table td { color: var(--text-secondary); font-size: .84rem; }
.users-table td strong { color: var(--text-primary); display: block; }
.users-table .user-name-cell { align-items: center; display: flex; gap: 0.625rem; }
.users-table .user-list-avatar { background: var(--bg-base); border: 1px solid var(--border-color); border-radius: 50%; flex-shrink: 0; height: 36px; object-fit: cover; width: 36px; }
.users-table .user-list-avatar-placeholder { align-items: center; color: var(--text-secondary); display: flex; font: 700 .9rem var(--font-display); justify-content: center; }
.users-table td.user-registered { white-space: nowrap; }
.users-table th.user-lists-head, .users-table td.user-lists { white-space: nowrap; font-variant-numeric: tabular-nums; }
.users-table td.user-registered .user-last-seen { color: var(--text-muted); }
.users-table td small { color: var(--accent-primary); display: block; }
.user-role { border-radius: 20px; display: inline-block; font: 700 .7rem var(--font-display); padding: 0.1875rem 0.5rem; text-transform: uppercase; }
.user-role-admin { background: rgba(var(--accent-primary-rgb),.12); color: var(--accent-primary); }
.user-role-user { background: rgba(var(--color-orders-rgb),.12); color: var(--color-orders); }
.user-actions, .form-actions { align-items: center; display: flex; gap: 0.4375rem; }
.user-actions form { margin: 0; }
/* A flex <td> leaves the table box model, so its border stops tracking the row
   and draws a stub beside the buttons. Keep action cells as real cells. */
.users-table td.user-actions { display: table-cell; vertical-align: middle; white-space: nowrap; }
.users-table td.user-actions > * { display: inline-block; margin: 0; vertical-align: middle; }
.users-table td.user-actions > * + * { margin-left: 7px; }
/* The rule above wins over .btn-premium's flex centring, which left the icon
   of an icon-only control pinned to the top left of its 34px box. Icon buttons
   stay inline in the cell and keep centring their glyph. */
.users-table td.user-actions > .action-icon-button { align-items: center; display: inline-flex; justify-content: center; }

/* Exposition catalogue --------------------------------------------------- */
/* Season sources: one card per calendar year. */
.season-source-grid { display: flex; flex-direction: column; gap: 1rem; margin-bottom: 28px; }
.season-source { display: flex; flex-direction: column; gap: 0.75rem; margin: 0; }
.season-source:hover { transform: none; }
.season-source-active { box-shadow: var(--shadow-premium), inset 0 0 0 1px rgba(var(--accent-primary-rgb),.35); }
.season-source-head { align-items: baseline; display: flex; gap: 0.625rem; justify-content: space-between; }
.season-source-head strong { color: var(--text-primary); font: 700 1rem var(--font-display); }
.season-source-year { background: rgba(var(--accent-primary-rgb),.12); border-radius: 20px; color: var(--accent-primary); font: 700 .68rem var(--font-display); padding: 0.1875rem 0.5625rem; }
.season-source-url { color: var(--text-muted); font-size: .76rem; overflow: hidden; text-decoration: none; text-overflow: ellipsis; white-space: nowrap; }
.season-source-url:hover { color: var(--accent-primary); }
.season-source-stats { border-top: 1px solid var(--border-color); display: flex; gap: 1.625rem; margin: 0; padding-top: 0.75rem; }
.season-source-stats dt { color: var(--text-muted); font: 700 .64rem var(--font-display); letter-spacing: .04em; text-transform: uppercase; }
.season-source-stats dd { color: var(--text-primary); font-size: .84rem; margin: 3px 0 0; }
.season-source-stats dd a { color: var(--accent-primary); text-decoration: none; }
.season-source-stats dd a:hover { text-decoration: underline; }
.season-source-result { color: var(--text-secondary); font-size: .76rem; margin: -4px 0 0; }
.season-source-actions { align-items: center; display: flex; gap: 0.5rem; margin-top: auto; }
.season-source-actions form { margin: 0; }
.season-source-actions .btn-premium { font-size: .74rem; padding: 0.5625rem 1rem; white-space: nowrap; width: auto; }

/* The narrated import. Hidden until a run starts, then a headline the reader
   watches and a log they can scroll back through — capped in height so a
   thirty-line run does not push the rest of the season grid off the screen. */
.season-import-run { border-top: 1px solid var(--border-color); display: flex; flex-direction: column; gap: 0.5rem; margin-top: 12px; padding-top: 0.75rem; }
.season-import-status { font-size: .78rem; line-height: 1.45; }
.season-import-status-running { color: var(--text-secondary); }
.season-import-status-ok { color: var(--accent-primary); }
.season-import-status-error { color: var(--color-my-dogs); }
.season-import-status a { color: var(--accent-primary); margin-left: 4px; }
.season-import-log { display: flex; flex-direction: column; gap: 0.25rem; list-style: none; margin: 0; max-height: 220px; overflow-y: auto; padding: 0; }
.season-import-line { color: var(--text-secondary); display: flex; font-size: .74rem; gap: 0.5rem; line-height: 1.4; }
.season-import-stage { color: var(--text-muted); flex: 0 0 52px; font: 700 .62rem var(--font-display); letter-spacing: .04em; padding-top: 0.125rem; text-transform: uppercase; }
.season-import-error span:last-child { color: var(--color-my-dogs); }
.season-import-warning span:last-child { color: var(--color-important); }
.season-import-done span:last-child { color: var(--accent-primary); }

/* Year picker: the year view of a date field, on its own. */
.year-picker { position: relative; }
/* The panel sits in the flow rather than floating over the form: its host modal
   clips to its rounded corners, so an absolutely positioned grid lost its last
   row. Opening it grows the dialog instead, and the body scrolls if that runs
   the modal past the viewport. */
.year-picker-panel { background: var(--bg-base); border: 1px solid var(--border-highlight); border-radius: var(--radius-md); margin-top: 6px; padding: 0.75rem; }
.year-picker-head { align-items: center; display: flex; justify-content: space-between; margin-bottom: 10px; }
.year-picker-range { color: var(--text-primary); font: 700 .84rem var(--font-display); }
.year-picker-nav { background: none; border: none; border-radius: var(--radius-sm); color: var(--text-secondary); cursor: pointer; font-size: 1.1rem; line-height: 1; padding: 0.25rem 0.625rem; }
.year-picker-nav:hover { background: var(--bg-overlay); color: var(--text-primary); }
.year-picker-grid { display: grid; gap: 0.375rem; grid-template-columns: repeat(3, 1fr); }
.year-picker-year { background: var(--bg-base); border: 1px solid transparent; border-radius: var(--radius-sm); color: var(--text-primary); cursor: pointer; font: 600 .84rem var(--font-display); padding: 0.5625rem 0; transition: var(--transition-premium); }
.year-picker-year:hover { background: var(--bg-overlay); }
.year-picker-year-now { border-color: rgba(var(--accent-primary-rgb),.45); }
.year-picker-year-active { background: var(--accent-primary); border-color: var(--accent-primary); color: #fff; }

/* Season tabs: the imported shows below belong to whichever year is active. */
.season-tabs { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-bottom: 16px; overflow-x: auto; }
.season-tab { align-items: center; border-bottom: 2px solid transparent; color: var(--text-secondary); display: inline-flex; font: 600 .86rem var(--font-display); gap: 0.4375rem; padding: 0.5625rem 0.875rem; text-decoration: none; transition: var(--transition-premium); white-space: nowrap; }
.season-tab:hover { background: var(--bg-overlay); color: var(--text-primary); }
.season-tab small { background: var(--bg-overlay); border-radius: 20px; color: var(--text-muted); font: 700 .68rem var(--font-display); padding: 0.125rem 0.4375rem; }
.season-tab-active { border-bottom-color: var(--accent-primary); color: var(--accent-primary); }
.season-tab-active small { background: rgba(var(--accent-primary-rgb),.14); color: var(--accent-primary); }

/* Imported shows: a card per show, its expositions listed inside. */
.expo-show-grid {
    display: grid;
    gap: 0.875rem;
}

.expo-show {
    margin: 0;
    padding: 0;
    container-type: inline-size;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    /* A #show-<id> link from the watch mail lands on the card, not under the
       fixed header and the card's own sticky head. */
    scroll-margin-top: calc(var(--header-height) + 1rem);
}

.expo-show:hover {
    transform: none;
}

/* The show name stays put while its expositions scroll, but it parks under the
   page header instead of at the viewport top -- and keeps --z-content, so a
   card can never paint over the header the way it did before. */
.expo-show-head {
    align-items: baseline;
    background: var(--bg-card);
    border-bottom: 1px solid var(--border-color);
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 0.75rem;
    justify-content: space-between;
    padding: 0.3125rem 0.9375rem 0.625rem 0.9375rem;
    position: sticky;
    top: var(--header-height);
    z-index: var(--z-content);
    border-top-left-radius: var(--radius-md);
    border-top-right-radius: var(--radius-md);
    box-sizing: content-box;
    /* The site's own `header` rule fixes every <header> at --header-height.
       This one is a card head that grows with its content: a check verdict on
       its own line pushed the place line out of a 66 px box and over the
       evidence strip below (DIM-631). */
    height: auto;
}


.expo-show-name {
    color: var(--text-primary);
    font: 700 .98rem var(--font-display);
    text-decoration: none;
}

.expo-show-name:hover {
    color: var(--accent-primary);
}

.expo-show-name:focus-visible {
    border-radius: 3px;
    outline: 2px solid var(--accent-primary);
    outline-offset: 3px;
}

/* The square-with-an-arrow beside the name: the exposition on cpc.pt. Sized to
   the check button next to it so the two read as one pair of controls. */
.expo-show-source {
    align-items: center;
    color: var(--text-muted);
    display: inline-flex;
    flex: 0 0 auto;
    justify-content: center;
    height: 26px;
    width: 26px;
    border-radius: 7px;
    text-decoration: none;
}

.expo-show-source .action-icon {
    height: 15px;
    width: 15px;
}

.expo-show-source:hover {
    background: var(--tint-subtle);
    color: var(--accent-primary);
}

.expo-show-source:focus-visible {
    outline: 2px solid var(--accent-primary);
    outline-offset: 2px;
}

.expo-show-name-orphan {
    color: var(--text-muted);
    font-style: italic;
    font-weight: 600;
}

/* The show's venue, once, on its own line at the foot of the head. The pin is
   decoration, hidden from screen readers, so it carries no spacing of its own. */
.expo-show-place {
    color: var(--text-muted);
    flex: 1 1 100%;
    font-size: .74rem;
}

.expo-show-place-pin {
    display: inline-block;
    height: 13px;
    margin-right: 4px;
    vertical-align: -2px;
    width: 13px;
}

.expo-show-meta {
    align-items: center;
    color: var(--text-muted);
    display: flex;
    flex-wrap: wrap;
    font-size: .76rem;
    gap: 0.5rem;
}

/* Catalogued and scheduled are two different imports. These say, at a glance,
   which shows still have no ring schedule behind them. */
.expo-schedule-pill { align-items: baseline; border: 1px solid transparent; border-radius: 999px; display: inline-flex; font: 700 .66rem var(--font-display); gap: 0.375rem; letter-spacing: .03em; padding: 0.1875rem 0.5625rem; white-space: nowrap; }
.expo-schedule-pill small { font-weight: 600; opacity: .75; }
.expo-schedule-complete { background: rgba(var(--color-friends-rgb), .12); border-color: rgba(var(--color-friends-rgb), .35); color: var(--color-friends); }
.expo-schedule-partial { background: rgba(var(--color-important-rgb), .12); border-color: rgba(var(--color-important-rgb), .35); color: var(--color-important); }
.expo-schedule-source_found { background: rgba(var(--accent-primary-rgb), .08); border-color: rgba(var(--accent-primary-rgb), .3); color: var(--accent-primary); }
.expo-schedule-missing { background: rgba(var(--color-my-dogs-rgb), .1); border-color: rgba(var(--color-my-dogs-rgb), .3); color: var(--color-my-dogs); }
.expo-schedule-stale { background: rgba(var(--accent-primary-rgb), .12); border-color: rgba(var(--accent-primary-rgb), .4); color: var(--accent-primary); }
.schedule-legend { display: flex; flex-wrap: wrap; gap: 0.375rem; }

/* The same pills are the quick filter, so they have to look pressable. While a
   filter is on, the states left out fade back instead of disappearing — the
   counts are still the point of the row. */
.expo-schedule-filter { appearance: none; cursor: pointer; transition: var(--transition-premium); }
.expo-schedule-filter:hover { filter: brightness(1.25); }
.expo-schedule-filter[aria-pressed="true"] { border-color: currentColor; box-shadow: 0 0 0 2px rgba(var(--accent-primary-rgb), .28); }
.schedule-legend[data-filter-active] .expo-schedule-filter[aria-pressed="false"] { opacity: .4; }

/* One import per show day, run straight from the row. */
.expo-days { display: grid; gap: 0.375rem; grid-column: 1 / -1; margin-top: 4px; }
.expo-day { align-items: center; background: rgba(var(--bg-overlay-rgb), .35); border: 1px solid var(--border-color); border-left: 3px solid var(--border-highlight); border-radius: 8px; display: flex; flex-wrap: wrap; gap: 0.625rem; padding: 0.4375rem 0.625rem; }
.expo-day-missing { border-left-color: rgba(var(--color-my-dogs-rgb), .5); }
.expo-day-imported { border-left-color: rgba(var(--color-friends-rgb), .5); }
.expo-day-stale { border-left-color: var(--accent-primary); }
.expo-day-date { color: var(--text-primary); font: 700 .74rem var(--font-display); min-width: 74px; }
.expo-day-state { color: var(--text-secondary); flex: 1 1 auto; font-size: .72rem; min-width: 0; }
.expo-day-state small { color: var(--text-muted); }
.expo-day-missing .expo-day-state { color: var(--color-my-dogs); }
.expo-day-imported .expo-day-state { color: var(--color-friends); }
.expo-day-stale .expo-day-state { color: var(--accent-primary); }
.expo-day-blocked { color: var(--text-muted); font-size: .7rem; font-style: italic; }
.expo-day-source-link { align-items: center; display: inline-flex; gap: 0.25rem; text-decoration: none; }
.expo-day-source-link:hover { color: var(--accent-primary); }
.expo-day-source-link .action-icon { height: 12px; width: 12px; }
.expo-day .expo-day-import { align-items: center; display: inline-flex; flex: 0 0 auto; gap: 0.375rem; width: auto; min-height: 0; padding: 0.3125rem 0.625rem; border-radius: 7px; font: 700 .68rem var(--font-display); }
.expo-day .expo-day-import .action-icon { height: 14px; width: 14px; }
.expo-day .expo-day-import:disabled { cursor: progress; opacity: .6; }
.expo-day .expo-day-url { align-items: center; display: inline-flex; flex: 0 0 auto; width: auto; min-height: 0; padding: 0.3125rem 0.4375rem; border-radius: 7px; }
.expo-day .expo-day-url .action-icon { height: 14px; width: 14px; }
.expo-day .expo-day-url:disabled { cursor: progress; opacity: .6; }
.expo-day-message { flex: 1 1 100%; font-size: .7rem; color: var(--text-secondary); margin: 2px 0 0; }
.expo-day-message-error { color: var(--color-my-dogs); }

/* The run's own account of itself, under the day it belongs to. Capped and
   scrollable: a day that follows three Horários pages writes a dozen lines, and
   the list of days must stay readable while one of them is running. */
.expo-day-log { flex: 1 1 100%; display: flex; flex-direction: column; gap: 0.1875rem; list-style: none; margin: 6px 0 0; max-height: 180px; overflow-y: auto; padding: 0; }
.expo-day-log-line { color: var(--text-secondary); display: flex; font-size: .7rem; gap: 0.5rem; line-height: 1.4; }
.expo-day-log-stage { color: var(--text-muted); flex: 0 0 46px; font: 700 .58rem var(--font-display); letter-spacing: .04em; padding-top: 0.0625rem; text-transform: uppercase; }
.expo-day-log-failed span:last-child { color: var(--color-my-dogs); }
.expo-day-log-error span:last-child { color: var(--color-my-dogs); }
.expo-day-log-done span:last-child { color: var(--accent-primary); }
/* What the importer found, under the day it was importing: the missing pieces,
   the page checks behind the verdict, and root's technical detail. */
.expo-day-diagnostics { flex: 1 1 100%; margin: 4px 0 0; }
.expo-day-diagnostics > * + * { margin-top: 4px; }
.expo-show-head .expo-show-check { align-items: center; display: inline-flex; flex: 0 0 auto; gap: 0.375rem; width: auto; min-height: 0; padding: 0.3125rem 0.5625rem; border-radius: 7px; font: 700 .68rem var(--font-display); letter-spacing: .04em; }
.expo-show-head .expo-show-check .action-icon { height: 15px; width: 15px; }

/* Everything that walks the whole list lives behind one trigger, so the
   section bar keeps one button no matter how many bulk runs there are. */
.bulk-actions { position: relative; }
.bulk-actions-trigger { align-items: center; display: inline-flex; gap: 0.375rem; justify-content: center; width: auto; }
.bulk-actions-menu { background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 12px; box-shadow: 0 8px 32px rgba(0,0,0,.4); display: flex; flex-direction: column; max-width: min(320px, 84vw); min-width: 240px; overflow: hidden; position: absolute; right: 0; top: calc(100% + 6px); z-index: var(--z-popover); }
.bulk-actions-menu[hidden] { display: none; }
/* The season importer's menu hangs off its own trigger, which already sits at
   the right of a wide bar. The lists page's trigger sits at the left, and a menu
   anchored to a narrow trigger has nowhere to go: right:0 pushes it off the left
   of the screen, left:0 off the right. So it is anchored to the action bar
   instead, which spans the content — the panel lines up with the right edge of
   the page whatever the button under it is called or how wide it is. */
/* An open list has one control and it sits at the right, where a thumb holding
   the phone already is — the list itself is read down the left. The menu hangs
   off the bar rather than off the button, because the button is narrow: right:0
   against it would push the panel off the left of the screen. Anchored to the
   bar, which spans the content, both the button and the panel line up with the
   right edge of the page. */
.page-action-bar-end { justify-content: flex-end; }
.page-action-bar { position: relative; }
.page-action-bar .bulk-actions { position: static; }
.page-action-bar .bulk-actions-menu { left: auto; right: 0; }
.bulk-actions-trigger .action-icon { height: 15px; width: 15px; }
.bulk-actions-menu .bulk-menu-item { display: grid; gap: 0.125rem; }
.bulk-actions-menu .bulk-menu-item small { color: var(--text-muted); font-size: .72rem; font-weight: 500; }
.bulk-actions-menu .bulk-menu-item + .bulk-menu-item { border-top: 1px solid rgba(var(--border-color-rgb),.7); }

/* A left rail repeats the state on the card itself, so the list can be read by
   shape instead of by reading every pill. */
.expo-show-complete { border-left: 3px solid rgba(var(--color-friends-rgb), .45); }
.expo-show-partial { border-left: 3px solid rgba(var(--color-important-rgb), .55); }
.expo-show-missing { border-left: 3px solid rgba(var(--color-my-dogs-rgb), .55); }

/* nowrap so the button always stays on the show name's line; a long name
   wraps its own text instead of pushing the button down. */
.expo-show-title { align-items: center; display: flex; flex-wrap: wrap; gap: 0.625rem; min-width: 0; }
/* The check's verdict takes the whole next line rather than squeezing the name:
   its evidence is several lines long once opened. */
.expo-show-title > .expo-check-result { flex: 1 1 100%; }
.expo-catalogue-url:not([hidden]) { align-items: center; display: inline-flex; flex: 1 1 100%; gap: 0.5rem; }
.expo-catalogue-url input { flex: 1 1 auto; max-width: 28rem; min-width: 0; }
.expo-show-title .expo-show-name { min-width: 0; }
/* Icon-only by default; the label appears when the card is wide enough.
   Scoped under .expo-show-head to outrank the later .btn-premium base rule,
   which is full width by default. */
.expo-show-head .expo-show-import { align-items: center; display: inline-flex; flex: 0 0 auto; gap: 0.375rem; width: auto; min-height: 0; padding: 0.3125rem 0.5625rem; border-radius: 7px; font: 700 .68rem var(--font-display); letter-spacing: .04em; }
.expo-show-head .expo-show-import .action-icon { height: 15px; width: 15px; }
.expo-show-head .expo-show-import-label { display: none; }
@container (min-width: 440px) { .expo-show-head .expo-show-import-label { display: inline; } }

.expo-list { display: grid; list-style: none; margin: 0; padding: 0; }
.expo-item { align-items: center; display: grid; gap: 0.375rem 1rem; grid-template-columns: 74px minmax(0, 1fr) auto auto; padding: 0.75rem 1.25rem; }
.expo-item + .expo-item { border-top: 1px solid rgba(var(--border-color-rgb),.7); }
.expo-date { color: var(--accent-primary); font: 700 .76rem var(--font-display); }
.expo-body { display: grid; gap: 0.125rem; min-width: 0; }
.expo-name { color: var(--text-primary); font-size: .86rem; }
.expo-place { color: var(--text-muted); font-size: .74rem; }
.expo-tags { display: flex; flex-wrap: wrap; gap: 0.3125rem; justify-content: flex-end; }
.expo-tag { background: rgba(var(--accent-primary-rgb),.1); border-radius: 20px; color: var(--accent-primary); font: 700 .64rem var(--font-display); padding: 0.1875rem 0.5625rem; white-space: nowrap; }
.expo-tag-open { background: rgba(var(--color-friends-rgb),.12); color: var(--color-friends); }
.expo-tag-muted { background: rgba(var(--text-muted-rgb),.14); color: var(--text-muted); }
.expo-tag-alert { background: rgba(var(--color-my-dogs-rgb),.14); color: var(--color-my-dogs); }
.expo-actions { margin: 0; }
.expo-item-removed .expo-name, .expo-item-removed .expo-place, .expo-item-removed .expo-date { opacity: .55; text-decoration: line-through; }

.import-warning-list { color: var(--text-secondary); font-size: .82rem; margin: 0; padding-left: 1.125rem; }
.import-warning-list li + li { margin-top: 6px; }

/* Single-show editor: two-column form, full-width fields where it helps. */
.show-edit-form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.show-edit-form .field-wide { grid-column: 1 / -1; }
.expo-edit-card { padding-top: 1rem; }
.expo-edit-card:hover { transform: none; }
.expo-edit-card-removed { opacity: .72; }
.expo-edit-head { align-items: center; border-bottom: 1px solid var(--border-color); display: flex; flex-wrap: wrap; gap: 0.375rem 0.75rem; margin-bottom: 18px; padding-bottom: 0.875rem; }
.expo-edit-head strong { color: var(--text-primary); font: 700 .92rem var(--font-display); margin-right: auto; }
.expo-edit-tools { align-items: center; border-top: 1px solid var(--border-color); display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 18px; padding-top: 0.875rem; }
.expo-edit-tools form { align-items: center; display: flex; gap: 0.5rem; margin: 0; }
.expo-edit-tools .btn-premium { font-size: .72rem; padding: 0.5rem 0.75rem; width: auto; }
.expo-move-form { margin-left: auto !important; }
.expo-move-form select { background: var(--bg-input); border: 1px solid var(--border-input); border-radius: var(--radius-sm); color: var(--text-primary); font: inherit; font-size: .78rem; max-width: 210px; padding: 0.4375rem 0.625rem; }
.expo-lock-note { align-items: center; background: rgba(var(--accent-primary-rgb),.07); border-radius: var(--radius-sm); color: var(--text-secondary); display: flex; flex-wrap: wrap; gap: 0.625rem; font-size: .8rem; justify-content: space-between; margin-top: 18px; padding: 0.75rem 0.875rem; }
/* Root's "use despite the mismatch" on a show card: a pill that is a button */
.expo-catalogue-accept { display: inline-flex; margin: 0; }
.expo-catalogue-explain { display: inline-flex; align-items: center; justify-content: center; padding: 0.125rem; border: 0; background: none; color: var(--text-secondary); cursor: pointer; }
.expo-catalogue-explain:hover, .expo-catalogue-explain:focus-visible { color: var(--accent-primary); }
.expo-catalogue-explain .action-icon { width: 1.25rem; height: 1.25rem; }
.catalogue-explain-status:empty { display: none; }
.catalogue-explain-part h3 { margin: 1rem 0 0.375rem; font-size: 0.95rem; }
.catalogue-explain-part:first-of-type h3 { margin-top: 0; }
.catalogue-explain-part ul { margin: 0; padding-left: 1.25rem; }
.catalogue-explain-part li { margin: 0.25rem 0; line-height: 1.4; }
.catalogue-explain-wrong h3 { color: var(--color-important); }
.expo-catalogue-accept-button { cursor: pointer; font: inherit; border: 1px solid currentColor; }

/* A show's catalogues on its settings page (settings/catalogue_panel.php) */
.catalogue-card:hover { transform: none; }
.catalogue-intro, .catalogue-empty { color: var(--text-secondary); font-size: .85rem; margin: 0 0 0.875rem; }
.catalogue-item { border-top: 1px solid var(--border-color); padding: 0.875rem 0; }
.catalogue-item-failed .catalogue-item-head strong { color: var(--accent-primary); }
.catalogue-item-head { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.375rem 0.75rem; }
.catalogue-item-head strong { color: var(--text-primary); font: 700 .88rem var(--font-display); }
.catalogue-source { color: var(--text-muted); font-size: .78rem; overflow-wrap: anywhere; }
.catalogue-exhibitions { color: var(--text-secondary); font-size: .82rem; margin: 0.5rem 0 0.625rem; padding-left: 1.1rem; }
.catalogue-item form .btn-premium { font-size: .72rem; padding: 0.5rem 0.75rem; width: auto; }
.catalogue-form { border-top: 1px solid var(--border-color); margin-top: 0.25rem; padding-top: 0.875rem; }
.expo-lock-note form { margin: 0; }
.expo-lock-note .btn-premium { font-size: .72rem; padding: 0.4375rem 0.6875rem; width: auto; }
.expo-danger-card { box-shadow: var(--shadow-premium), inset 0 0 0 1px rgba(var(--color-my-dogs-rgb),.25); }
.expo-danger-card:hover { transform: none; }
.expo-danger-card .settings-intro { margin-bottom: 14px; }
.expo-danger-card .btn-premium { width: auto; }

@media (max-width: 640px) {
    .show-edit-form { grid-template-columns: minmax(0, 1fr); }
    /* Keep Move and the delete button sharing one line instead of stacking. */
    .expo-move-form { flex: 1 1 160px; margin-left: 0 !important; }
    .expo-move-form select { flex: 1; max-width: none; min-width: 0; }
}

@media (max-width: 720px) {
    .expo-item { grid-template-columns: minmax(0, 1fr) auto; }
    .expo-date { grid-column: 1; }
    .expo-body { grid-column: 1 / -1; }
    .expo-tags { grid-column: 1; justify-content: flex-start; }
    .expo-actions { grid-column: 2; grid-row: 1; justify-self: end; }
}
.user-actions .btn-premium, .form-actions .btn-premium { font-size: .7rem; padding: 0.4375rem 0.5625rem; text-decoration: none; width: auto; }
.btn-danger { background: rgba(var(--color-my-dogs-rgb),.12); color: var(--color-my-dogs); }
.btn-danger:hover { background: rgba(var(--color-my-dogs-rgb),.22); }
.action-icon-button { flex: 0 0 34px; height: 34px; padding: 0 !important; width: 34px !important; }
.action-icon { display: block; height: 17px; width: 17px; }
.auth-page { align-items: center; display: flex; justify-content: center; min-height: 100vh; padding: 1.5rem; }
.auth-card { background: var(--bg-surface); border: 1px solid var(--border-color); border-radius: var(--radius-lg); box-shadow: var(--shadow-premium); max-width: 420px; padding: 2rem; width: 100%; }
.auth-card h1 { font: 800 1.8rem var(--font-display); margin-top: 24px; }
.auth-card > p { color: var(--text-secondary); margin: 4px 0 22px; }
.auth-card .auth-switch { border-top: 1px solid var(--border-color); font-size: .8rem; margin: 22px 0 0; padding-top: 1.125rem; text-align: center; }
.auth-switch a { align-items: center; color: var(--accent-primary); display: inline-flex; font-weight: 700; gap: 0.25rem; text-decoration: none; }
.database-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.database-actions p { color: var(--text-muted); font-size: .75rem; margin-top: 5px; max-width: 220px; }
/* clip, not hidden: hidden makes the card a scroll container and the head would stick to it instead of the page. */
.test-dashboard { background: var(--bg-surface); border: 1px solid var(--border-color); border-radius: var(--radius-md); box-shadow: var(--shadow-premium); overflow: clip; }
.test-dashboard-summary { align-items: center; background: linear-gradient(110deg, var(--bg-card), var(--bg-surface)); border-bottom: 1px solid var(--border-color); display: flex; gap: 1rem; justify-content: space-between; padding: 1.125rem 1.25rem; }
.test-dashboard-summary strong { display: block; font: 700 1.05rem var(--font-display); }
.test-dashboard-summary span { color: var(--text-muted); font-size: .8rem; }
.test-dashboard-summary .test-progress { color: var(--text-primary); display: block; font: 700 1rem var(--font-display); font-variant-numeric: tabular-nums; margin-top: 0.25rem; }
.test-dashboard-actions { display: flex; gap: 0.5rem; }
.test-dashboard-actions .btn-premium { font-size: .76rem; padding: 0.5rem 0.6875rem; }
/* Title, run buttons and tallies park under the site header while the table scrolls. */
.test-dashboard-head { background: var(--bg-surface); border-bottom: 1px solid var(--border-color); position: sticky; top: var(--header-height); z-index: var(--z-content); }
.test-command { align-items: flex-end; color: var(--text-secondary); display: flex; flex-wrap: wrap; font-size: .8rem; gap: 0.5rem; padding: 0.875rem 1.25rem 0.75rem; }
.test-command span { color: var(--text-muted); display: block; font-size: .7rem; margin-bottom: 4px; text-transform: uppercase; }
/* The label keeps its own line above the command; the tallies sit off to the right. */
.test-command > span:first-child { flex-basis: 100%; margin-bottom: 0; }
.test-command code { background: var(--bg-base); border: 1px solid var(--border-color); border-radius: 5px; color: var(--text-primary); display: inline-block; padding: 0.3125rem 0.5rem; }

/* Tally and filter in one control: the number says how many, pressing it shows which. */
.test-command .test-filters { display: inline-flex; gap: 0.375rem; margin-bottom: 0; margin-left: auto; }
.test-filter { background: var(--bg-base); border: 1px solid var(--border-color); border-radius: 5px; color: var(--text-muted); cursor: pointer; font: 700 .68rem var(--font-display); letter-spacing: .04em; padding: 0.3125rem 0.5625rem; }
.test-filter span { color: var(--text-primary); display: inline; font-size: .78rem; margin: 0 0 0 5px; text-transform: none; }
.test-filter:hover { border-color: var(--text-muted); }
/* Each tally wears its state's colour at rest; pressing it fills the chip. */
.test-filter-passed { border-color: rgba(var(--color-friends-rgb),.45); color: var(--color-friends); }
.test-filter-warning { border-color: rgba(var(--color-important-rgb),.45); color: var(--color-important); }
.test-filter-skipped { border-color: rgba(var(--color-orders-rgb),.45); color: var(--color-orders); }
.test-filter-failed { border-color: rgba(var(--color-my-dogs-rgb),.45); color: var(--color-my-dogs); }
.test-filter-passed:hover { border-color: var(--color-friends); }
.test-filter-warning:hover { border-color: var(--color-important); }
.test-filter-skipped:hover { border-color: var(--color-orders); }
.test-filter-failed:hover { border-color: var(--color-my-dogs); }
.test-filter span { color: inherit; }
.test-filter-passed[aria-pressed="true"] { background: rgba(var(--color-friends-rgb),.16); border-color: var(--color-friends); color: var(--color-friends); }
.test-filter-warning[aria-pressed="true"] { background: rgba(var(--color-important-rgb),.16); border-color: var(--color-important); color: var(--color-important); }
.test-filter-skipped[aria-pressed="true"] { background: rgba(var(--color-orders-rgb),.16); border-color: var(--color-orders); color: var(--color-orders); }
.test-filter-failed[aria-pressed="true"] { background: rgba(var(--color-my-dogs-rgb),.16); border-color: var(--color-my-dogs); color: var(--color-my-dogs); }
.test-filter[aria-pressed="true"] span { color: inherit; }
.test-table-wrap { overflow-x: auto; padding: 0.875rem 1.25rem 1.25rem; }
.test-table { border-collapse: collapse; min-width: 620px; width: 100%; }
.test-table th { border-bottom: 1px solid var(--border-color); color: var(--text-muted); font: 700 .7rem var(--font-display); letter-spacing: .05em; padding: 0.5625rem 0.5rem; text-align: left; text-transform: uppercase; }
.test-table td { border-bottom: 1px solid rgba(var(--border-color-rgb),.7); color: var(--text-secondary); font-size: .82rem; padding: 0.8125rem 0.5rem; vertical-align: top; }
.test-table tr:last-child td { border-bottom: 0; }
.test-table strong { color: var(--text-primary); display: block; font-family: var(--font-display); }
.test-table small { color: var(--text-muted); display: block; font: .73rem monospace; margin-top: 2px; }
.test-table input { accent-color: var(--accent-primary); cursor: pointer; }
.test-status { font-family: var(--font-display); font-weight: 700; }
.test-status.passed { color: var(--color-friends); }
.test-status.failed { color: var(--color-my-dogs); }
.test-status.skipped { color: var(--color-orders); }
.test-status.warning { color: var(--color-important); }
/* The row currently executing, while the run walks the table one test at a time. */
.test-status.running { color: var(--color-important); }
.test-copy { align-items: center; background: transparent; border: 1px solid var(--border-color); border-radius: var(--radius-sm, 6px); color: var(--text-muted); cursor: pointer; display: inline-flex; height: 1.75rem; justify-content: center; margin-left: 0.5rem; padding: 0; vertical-align: middle; width: 1.75rem; }
.test-copy svg { fill: none; height: 0.95rem; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 2; width: 0.95rem; }
.test-copy:hover, .test-copy:focus-visible { border-color: var(--color-my-dogs); color: var(--text-primary); }
.test-copy.copied { border-color: var(--color-friends); color: var(--color-friends); }
.visually-hidden-copy { left: -9999px; opacity: 0; position: fixed; top: 0; }
.test-table details { color: var(--text-primary); cursor: pointer; }
.test-table summary { font-size: .78rem; }
.test-table pre { color: var(--text-secondary); font: .72rem/1.4 monospace; margin-top: 8px; max-width: 300px; white-space: pre-wrap; }
@media (max-width: 560px) { .test-dashboard-summary { align-items: stretch; flex-direction: column; } .test-dashboard-actions .btn-premium { flex: 1; } }
@media (max-width: 620px) { .settings-menu { grid-template-columns: 1fr; } }
@media (max-width: 700px) { .judges-directory { grid-template-columns: 1fr; } }
@media (max-width: 760px) { .judge-edit-layout { grid-template-columns: 1fr; } }
@media (hover: none), (pointer: coarse) { .judge-card-controls { opacity: 1; pointer-events: auto; transform: none; } }
@media (max-width: 520px) { .settings-section-bar, .directory-tools { align-items: stretch; flex-direction: column; } .judge-card-heading { align-items: flex-start; flex-wrap: wrap; } .judge-card-controls { margin-left: 54px; } }
/* The tools row stacks its own children on a narrow screen, and a stretched
   column makes every button full width. The buttons here are short labels next
   to a count, so the row stays a row that wraps, and they keep their own size. */
@media (max-width: 520px) {
    /* flex-end so that if the row does wrap on a very narrow screen, what
       wrapped stays with the buttons on the right rather than starting a new
       left-aligned line of its own. */
    .directory-tools { align-items: center; flex-direction: row; flex-wrap: wrap; justify-content: flex-end; }
    .directory-tools .btn-premium { flex: 0 0 auto; width: auto; }
    /* The tools row is full width once the section bar stacks, so the count
       holds the left edge and the buttons are pushed to the right together. */
    .directory-tools .directory-count { margin-right: auto; }
}
@media (max-width: 520px) { .header-tools { gap: 0; } .account-avatar { height: 30px; margin: 0 8px; width: 30px; } .account-avatar svg { height: 17px; width: 17px; } }
@media (max-width: 620px) { .benefit-banner { align-items: stretch; flex-direction: column; } .benefit-actions .btn-premium { flex: 1; } }

/* Upcoming Table Layout (Distinctive, minimalist approach) */
.matches-list {
    background-color: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    overflow: hidden;
    margin-bottom: 24px;
    box-shadow: var(--shadow-premium);
}

.match-item {
    display: grid;
    grid-template-columns: 70px 1fr 100px;
    align-items: center;
    padding: 0.3125rem 0.3125rem 0.3125rem 1.25rem;
    border-bottom: 1px solid var(--border-color);
    position: relative;
    transition: var(--transition-premium);
}

.match-item:last-child {
    border-bottom: none;
}

.match-item:hover {
    background-color: var(--tint-subtle);
}

.match-priority-indicator {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 4px;
    background-color: var(--prio-color, var(--border-color));
}

.match-time-ring {
    display: flex;
    flex-direction: column;
}

.match-time {
    font-family: var(--font-display);
    font-size: 0.95rem;
    font-weight: 800;
    line-height: 1.1;
    color: var(--text-primary);
}

/* The tracker's two switches. Both read as ticks, so the off state is a real
   button rather than an absence — the pair has to look like two independent
   things, not like one choice with two options. */
.tracker-filters { display: flex; gap: 0.5rem; justify-content: flex-end; margin-bottom: 14px; }
.tracker-filter {
    align-items: center;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    color: var(--text-muted);
    display: inline-flex;
    font: 700 .78rem var(--font-display);
    gap: 0.375rem;
    padding: 0.375rem 0.875rem;
    text-decoration: none;
    transition: var(--transition-premium);
}
.tracker-filter.active {
    background: rgba(var(--accent-primary-rgb), .14);
    border-color: var(--accent-primary);
    color: var(--text-primary);
}
.tracker-filter:not(.active) .favorite-star { color: var(--border-color); }

/* Said beside the Rings heading only while a ring is actually working. */
.live-tag {
    background: var(--color-friends);
    border-radius: 4px;
    color: #06210F;
    display: inline-block;
    font: 800 .62rem var(--font-display);
    letter-spacing: .06em;
    margin-left: 8px;
    padding: 0.1875rem 0.4375rem;
    text-transform: uppercase;
    vertical-align: middle;
}

.breed-lists-check {
    align-items: center;
    cursor: pointer;
    display: flex;
    font-family: var(--font-display);
    font-weight: 600;
    gap: 0.625rem;
}
.breed-lists-check input { height: 18px; width: 18px; accent-color: var(--accent-primary); }
.breed-lists-lists { display: flex; flex-direction: column; gap: 0.75rem; }
.breed-lists-lists .group-form { margin: 0; }

/* The star that marks a favourite. Hollow until it is one, and always in the
   accent colour, so one glance down a list finds them. */
.favorite-star {
    background: none;
    border: 0;
    color: var(--border-color);
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
    padding: 0 0.25rem 0 0;
    transition: var(--transition-premium);
}
.favorite-star.is-favorite { color: var(--accent-primary); }
@media (hover: hover) {
    .favorite-star:hover { color: var(--accent-primary); }
}

/* A breed that sits on one of the viewer's lists carries that list's colour
   after its name, so a ring reads for one's own dogs without being read. */
/* Beside a time that is not the one the timetable printed. */
.time-shifted {
    background: var(--color-my-dogs);
    border-radius: 50%;
    display: inline-block;
    height: 6px;
    margin-left: 0;
    vertical-align: middle;
    width: 6px;
}

.breed-list-dot {
    border-radius: 50%;
    display: inline-block;
    height: 7px;
    margin-left: 2px;
    vertical-align: middle;
    width: 7px;
}

.time-ahead {
    display: block;
    font-family: var(--font-display);
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--text-muted);
}

/* The ring is a jump to that ring's card, so it is a button — styled as the
   label it has always been, and reachable from a keyboard because of it. */
.match-ring {
    background: none;
    border: 0;
    cursor: pointer;
    padding: 0;
    text-align: left;
    font-family: var(--font-display);
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--accent-primary);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding-top: 0.25rem;
}

.match-details {
    display: flex;
    flex-direction: column;
    padding-right: 0.75rem;
}

.match-breed {
    font-family: var(--font-display);
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text-primary);
    line-height: 1.2;
    padding-bottom: 0.125rem;
}

.match-meta {
    align-items: center;
    display: flex;
    gap: 0.25rem;
    justify-content: flex-end;
    text-align: right;
}

.match-dogs {
    font-size: 0.86rem;
    color: var(--text-secondary);
}

.match-order {
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* The tracker: folded by its heading, passed breeds behind an eye, any row
   shrunk to one quiet line by a swipe (Dimas, 2026-10-26). No size is new:
   every font here is one the tracker already used. */
.tracker-header { margin-bottom: 8px; }
.tracker-fold {
    align-items: center;
    background: none;
    border: 0;
    color: inherit;
    cursor: pointer;
    display: inline-flex;
    font: inherit;
    gap: 0.4rem;
    letter-spacing: inherit;
    padding: 0;
    text-transform: inherit;
}
.tracker-chevron { height: 1em; transition: transform .15s; width: 1em; }
.tracker-header[data-folded] .tracker-chevron { transform: rotate(-90deg); }
.tracker-eye {
    align-items: center;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    color: var(--text-muted);
    cursor: pointer;
    display: inline-flex;
    line-height: 0;
    order: 1;
    padding: 0.375rem 0.625rem;
}
.tracker-eye[aria-pressed="true"] {
    background: rgba(var(--accent-primary-rgb), .14);
    border-color: var(--accent-primary);
    color: var(--text-primary);
}
.tracker-eye .action-icon { height: 1.4rem; width: 1.4rem; }
.tracker-header[data-folded] .tracker-eye { display: none; }
[data-tracker][data-folded] { display: none; }

.match-item { touch-action: pan-y; }
.match-shrink { background: none; border: 0; color: var(--text-muted); cursor: pointer; line-height: 0; padding: 0.25rem; }
.match-shrink .action-icon { height: 1em; transform: rotate(180deg); width: 1em; }
.match-item.is-shrunk .match-shrink .action-icon { transform: none; }
.match-item.is-passed .match-shrink { display: none; }
.match-title { align-items: flex-start; display: flex; gap: 0.25rem; }
.match-marks { flex: none; white-space: nowrap; }
.match-text { display: flex; flex-direction: column; min-width: 0; }
.match-title .match-breed { padding-bottom: 0; }
.match-details { padding-bottom: 0.25rem; padding-top: 0.25rem; }
.match-note { color: var(--text-muted); font-size: 0.75rem; line-height: 1.2; }
.match-left { color: var(--text-secondary); font-size: 0.75rem; }
.match-empty { color: var(--text-muted); font-size: 0.8rem; padding: 0.5rem 1.25rem; }

.match-item.is-passed { display: none; opacity: .6; }
.match-item.is-passed.is-latest-passed,
[data-tracker].show-passed .match-item.is-passed { display: grid; }

.match-item.is-shrunk {
    grid-template-columns: auto 1fr auto;
    opacity: .5;
    padding-bottom: 0.125rem;
    padding-top: 0.125rem;
}
.match-item.is-shrunk > * { min-width: 0; }
.match-item.is-shrunk .match-time-ring { align-items: baseline; flex-direction: row; gap: 0.5rem; }
.match-item.is-shrunk .match-time,
.match-item.is-shrunk .match-ring,
.match-item.is-shrunk .match-breed,
.match-item.is-shrunk .match-dogs,
.match-item.is-shrunk .match-note,
.match-item.is-shrunk .match-left { font-size: 0.65rem; line-height: 1.2; padding: 0; }
.match-item.is-shrunk .match-details {
    align-items: center;
    flex-direction: row;
    gap: 0.375rem;
    overflow: hidden;
    padding-bottom: 0;
    padding-top: 0;
    white-space: nowrap;
}
.match-item.is-shrunk .match-title { align-items: center; }
.match-item.is-shrunk .match-text { align-items: center; flex-direction: row; gap: 0.375rem; min-width: 0; }
.match-item.is-shrunk .match-note { overflow: hidden; text-overflow: ellipsis; }
.match-item.is-shrunk .match-breed { overflow: hidden; text-overflow: ellipsis; }

/* LIVE RING TRACKER (Signature Element Grid) */
.rings-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
    margin-bottom: 32px;
}

@media (min-width: 600px) {
    .rings-grid {
        grid-template-columns: 1fr 1fr;
    }
}

.ring-node {
    background-color: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    padding: 1.25rem;
    box-shadow: var(--shadow-premium);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    position: relative;
    overflow: hidden;
    transition: var(--transition-premium);
}

.ring-node:hover {
    border-color: var(--border-highlight);
    box-shadow: 0 15px 35px -10px rgba(0,0,0,0.8);
}

.ring-node.active-ring {
    border-color: rgba(var(--accent-primary-rgb), 0.4);
    box-shadow: 0 0 20px rgba(var(--accent-primary-rgb), 0.1);
}

.ring-node-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1.25rem;
    margin-bottom: 16px;
}

.ring-node-heading {
    min-width: 0;
}

.ring-node-title {
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 800;
    color: var(--text-primary);
}

.ring-node-judge {
    font-size: 0.75rem;
    color: var(--text-muted);
    line-height: 1.25;
    margin-top: 2px;
    /*max-width: 55%;*/
    text-align: right;
}

.ring-node-judge span,
.ring-node-judge strong {
    display: block;
}

.ring-node-judge strong {
    color: var(--text-secondary);
    font-weight: 600;
}

.ring-node-delay {
    display: inline-block;
    font-size: 0.75rem;
    font-weight: 700;
    margin-top: 6px;
    padding: 0.1875rem 0.5rem;
    border-radius: 6px;
}

/* Red, not amber: a late ring is the one thing on the card that changes what
   you do next, and amber reads as a note. The palette's red is the same one
   errors use. */
.ring-node-delay.delayed {
    background-color: rgba(var(--color-my-dogs-rgb), 0.12);
    color: var(--color-my-dogs);
    border: 1px solid rgba(var(--color-my-dogs-rgb), 0.3);
}

.ring-node-delay.early {
    background-color: rgba(var(--color-friends-rgb), 0.1);
    color: var(--color-friends);
    border: 1px solid rgba(var(--color-friends-rgb), 0.2);
}

.ring-th-delay { float: right; font-size: 0.64rem; font-weight: 700; letter-spacing: 0; text-transform: none; }
.ring-th-delay.delayed { color: var(--color-my-dogs); }
.ring-th-delay.early { color: var(--color-friends); }

.ring-node-body {
    background-color: rgba(var(--bg-base-rgb), 0.4);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 0.875rem;
    margin-bottom: 16px;
}

.ring-sequence-row {
    align-items: baseline;
    display: grid;
    gap: 0.625rem;
    grid-template-columns: 46px minmax(0, 1fr);
    line-height: 1.25;
    min-width: 0;
}

.ring-sequence-row + .ring-sequence-row {
    margin-top: 10px;
}

.ring-sequence-row time {
    font-variant-numeric: tabular-nums;
}

.ring-sequence-muted {
    color: var(--text-muted);
    font-size: 0.78rem;
    font-weight: 400;
}

.ring-sequence-muted span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ring-sequence-current {
    color: var(--text-primary);
    font-family: var(--font-display);
    font-size: 1.17rem;
    font-weight: 800;
}

.ring-sequence-current strong {
    min-width: 0;
    overflow-wrap: anywhere;
}

.ring-sequence-current small {
    color: var(--text-secondary);
    font-size: 0.68em;
    font-weight: 600;
    white-space: nowrap;
}

/* Button & UI elements */
.btn-premium {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 0.75rem;
    border-radius: var(--radius-sm);
    border: none;
    cursor: pointer;
    transition: var(--transition-premium);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    width: 100%;
    /* An <a> styled as a button is still a link to the browser: it arrives
       underlined and in the visited colour unless both are said here. */
    text-decoration: none;
    color: var(--text-primary);
}

.btn-premium-primary {
    background-color: var(--accent-primary);
    color: white;
    box-shadow: 0 4px 15px rgba(var(--accent-primary-rgb), 0.2);
}

.btn-premium-primary:hover {
    background-color: #E06B00;
    box-shadow: 0 6px 20px rgba(var(--accent-primary-rgb), 0.35);
}

.btn-premium-secondary {
    background-color: var(--bg-overlay);
    color: var(--text-primary);
    border: 1px solid var(--border-color);
}

.btn-premium-secondary:hover {
    background-color: var(--tint-subtle-strong);
}

/* Lists styling */
.list-item-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.875rem 0;
    border-bottom: 1px solid var(--border-color);
}

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

/* Forms styling */
.group-form {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.input-field {
    width: 100%;
    background-color: var(--bg-input);
    border: 1px solid var(--border-input);
    border-radius: var(--radius-sm);
    padding: 0.75rem 1rem;
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 0.95rem;
    transition: var(--transition-premium);
}

.input-field:focus {
    outline: none;
    border-color: var(--accent-primary);
    box-shadow: 0 0 0 3px rgba(var(--accent-primary-rgb), 0.15);
}

.input-field[type="date"]::-webkit-calendar-picker-indicator,
.input-field[type="time"]::-webkit-calendar-picker-indicator {
    filter: invert(1) brightness(2);
    cursor: pointer;
}

.label-field {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-secondary);
    margin-bottom: 6px;
    display: block;
}

/* A row of buttons that open the page's modals, standing where the form it
   replaced used to be. */
.page-action-bar { display: flex; flex-wrap: wrap; gap: 0.625rem; margin-top: 20px; }
/* .btn-premium is a full-width block by default, which is right inside a form
   and wrong in a row of actions: one button there stretched across the page and
   read as a banner rather than as something to press. Here each button is as
   wide as its own words. */
.page-action-bar .btn-premium { flex: 0 0 auto; width: auto; }

/* Not even on a phone: a button as wide as the screen reads as a banner, and
   these are ordinary actions. They wrap onto the next line instead. */
.page-action-bar .btn-premium { max-width: 100%; }

.modal-lede { color: var(--text-secondary); font-size: .84rem; margin-bottom: 16px; }
.color-field-row input[type="color"] { background: var(--bg-input); border: 1px solid var(--border-input); border-radius: 7px; height: 42px; padding: 0.1875rem; width: 60px; }

/* Autocomplete suggestion popups */
.autocomplete-container {
    position: relative;
}

.suggestions-box {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background-color: var(--bg-surface);
    border: 1px solid var(--border-highlight);
    border-radius: var(--radius-sm);
    max-height: 220px;
    overflow-y: auto;
    z-index: var(--z-popover);
    box-shadow: 0 10px 25px rgba(0,0,0,0.8);
}

.suggestion-node {
    padding: 0.75rem 1rem;
    cursor: pointer;
    border-bottom: 1px solid var(--border-color);
    transition: var(--transition-premium);
}

.suggestion-node:hover {
    background-color: var(--bg-overlay);
}

.modal-body .suggestions-box { position: static; margin-top: 6px; box-shadow: none; max-height: 190px; }

/* Bottom Bar PWA Navigation */

/* Five tabs, and the middle one is not a tab.

   The dashboard is where every other page leads back to, and it used to be the
   first of five identical cells — the far corner of a phone, the last place a
   thumb reaches. It is now a circle in the centre of the bar, standing above
   it, with the other four pushed in towards it. The bar is shorter than it was
   by exactly enough for the circle to stand proud without growing the strip of
   screen the navigation costs. */
.bar-nav {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: rgba(var(--bg-surface-rgb), 0.96);
    backdrop-filter: blur(16px);
    border-top: 1px solid var(--border-color);
    padding: 0;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    /* Above all page content, and level with the sticky header. */
    z-index: var(--z-chrome);
    box-shadow: 0 -10px 30px rgba(0,0,0,0.5);
    /* viewport-fit=cover: keep the tabs clear of the iOS home indicator. */
    padding-bottom: env(safe-area-inset-bottom, 0px);
}

.bar-tab {
    display: flex;
    flex-direction: column;
    align-items: center;
    color: var(--text-secondary);
    text-decoration: none;
    font-size: 0.7rem;
    font-family: var(--font-display);
    font-weight: 600;
    gap: 0.1875rem;
    transition: var(--transition-premium);
    padding: 0.375rem 0.375rem 0.4375rem;
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
    /* The four ordinary tabs share the bar evenly. min-width:0 lets a long word
       ellipsise inside its own tab instead of pushing the neighbours off. */
    flex: 1 1 0;
    min-width: 0;
    /* Room in the middle for the circle, which is taken out of the flow. */
    max-width: 5.5rem;
}

.bar-tab-word {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bar-icon { display: block; }

.bar-icon-glyph {
    display: block;
    height: 22px;
    width: 22px;
}

.bar-tab:hover {
    color: var(--text-primary);
    background-color: var(--tint-subtle);
}

.bar-tab.active {
    color: var(--accent-primary);
    background-color: rgba(var(--accent-primary-rgb), 0.08);
    border-color: rgba(var(--accent-primary-rgb), 0.2);
    box-shadow: inset 0 0 10px rgba(var(--accent-primary-rgb), 0.05);
}

/* The hub: a circle lifted clear of the bar, wider than a tab and taller than
   the bar it sits in. It stands well proud rather than merely peeping over the
   edge — half of it is above the border, which is what makes it read as one
   button rather than as a fifth tab with a round background.

   margin-top is negative by the amount it rises, so the bar's own height is
   unchanged and the page below it needs no extra clearance. */
.bar-tab-hub {
    align-items: center;
    background: linear-gradient(160deg, var(--accent-primary) 0%, rgba(var(--accent-primary-rgb), .78) 100%);
    border: 3px solid var(--bg-surface);
    border-radius: 999px;
    box-shadow: 0 6px 18px rgba(var(--accent-primary-rgb), .45);
    color: #fff;
    flex: 0 0 auto;
    gap: 0;
    height: 68px;
    justify-content: center;
    margin: -32px 0.625rem 0;
    padding: 0;
    width: 68px;
}

.bar-tab-hub:hover,
.bar-tab-hub.active {
    background-color: transparent;
    border-color: var(--bg-surface);
    box-shadow: 0 8px 22px rgba(var(--accent-primary-rgb), .6);
    color: #fff;
}

/* The circle says which page it is by being the circle. Its word would have to
   sit outside it, on the bar, level with nothing. */
.bar-tab-hub .bar-tab-word { display: none; }

.bar-tab-hub .bar-icon-glyph {
    height: 30px;
    stroke-width: 1.8;
    width: 30px;
}

/* --- Navigation feedback ---------------------------------------------------- */

/* The instant answer to a tap on a link: an orange strip along the header's
   bottom edge that creeps toward the right and does not arrive while the old
   page is waiting, a pressed look on the link itself, and a line under the
   header if the page is still not here after 8 seconds. initNavigationFeedback()
   in app.js sets html.is-navigating and .nav-pending.

   The strip never blinks: on pagehide app.js stores how far it got, and
   nav-arrive.js (in <head>, so before first paint) puts html.nav-arriving and
   --nav-from on the new page. The strip is in the header markup, so it exists
   at first paint and nav-finish carries it from there to 100% and fades it. */
.nav-progress {
    background: var(--nav-progress);
    border-radius: 0 2px 2px 0;
    bottom: -1px;
    height: 2px;
    left: 0;
    opacity: 0;
    pointer-events: none;
    position: absolute;
    width: 0;
}

.nav-progress::after {
    background: var(--nav-progress);
    border-radius: 999px;
    box-shadow: 0 0 6px 1px var(--accent-glow), 0 0 12px 3px rgba(var(--accent-primary-rgb), .45);
    content: "";
    height: 2px;
    position: absolute;
    right: 0;
    top: 50%;
    transform: translate(50%, -50%);
    width: 12px;
}

/* Declared before is-navigating, so a new tap wins over a finishing strip. */
html.nav-arriving .nav-progress {
    animation: nav-finish .55s ease-out forwards;
}

/* One curve over the whole run, with a soft start. The timing function
   applies to each keyframe segment, so the old 0/5/30/100% stops shot to 30%
   in 0.6 s, braked, and lunged again (Dimas, 2026-10-27: smoother start). */
html.is-navigating .nav-progress {
    animation: nav-progress 12s cubic-bezier(.3, .55, .25, 1) forwards,
               nav-progress-in .2s ease-out forwards;
}

@keyframes nav-progress {
    from { width: 0; }
    to { width: 92%; }
}

@keyframes nav-progress-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* The page has arrived: continue from where the last page left the strip. */
@keyframes nav-finish {
    0% { width: var(--nav-from, 30%); opacity: 1; }
    45% { width: 100%; opacity: 1; }
    100% { width: 100%; opacity: 0; }
}


.bar-tab .bar-icon { transition: transform .12s ease-out; }

.bar-tab.nav-pending { color: var(--nav-progress); }
.bar-tab.nav-pending .bar-icon { transform: scale(.86); }

.bar-tab-hub.nav-pending {
    /* The hub is orange already, so an orange ring would not show. */
    box-shadow: 0 0 0 3px rgba(255, 255, 255, .35), 0 8px 22px rgba(var(--accent-primary-rgb), .6);
    color: #fff;
    transform: scale(.92);
}

a.nav-pending:not(.bar-tab) { opacity: .65; }

.nav-slow {
    background: rgba(var(--bg-surface-rgb), .95);
    border: 1px solid rgba(var(--accent-primary-rgb), .5);
    border-radius: 999px;
    color: var(--text-primary);
    font: 600 .78rem var(--font-display);
    left: 50%;
    max-width: calc(100vw - 2rem);
    overflow: hidden;
    padding: .375rem .75rem;
    position: absolute;
    text-overflow: ellipsis;
    top: 100%;
    transform: translate(-50%, .375rem);
    white-space: nowrap;
}

.nav-slow[hidden] { display: none; }

/* Reduced motion keeps the strip: a 2px progress line is the answer the
   reader is waiting for, not decoration, and a static or fading-only strip
   was exactly the blink it exists to remove (Dimas, 2026-10-27). */
@media (prefers-reduced-motion: reduce) {
    .bar-tab .bar-icon { transition: none; }
}

/* --- Viewport slip (iOS 26 WebKit) ---------------------------------------- */

/* Where the screen really is, when WebKit has lost it.

   On iOS 26, after a text field has had the keyboard and let it go, the layout
   viewport -- the box position:fixed and position:sticky are measured against --
   can stay shifted down inside the screen (WebKit bug 297779, Apple
   FB19889436). The header leaves the top of the screen and the bottom bar sits
   across the middle of the page; in a home-screen app nothing ever puts it
   back, which is why the bar is right in Safari and floats in the app (Dimas,
   2026-10-21). initViewportAnchor() in app.js measures the shift from the
   visual viewport and writes it into these two properties; wherever the browser
   behaves they stay 0px and nothing here moves.

   translate rather than transform, because it composes with the transform a
   rule already has (the saving pill's translateX, the pull indicator's
   translateY) instead of replacing it. The modal overlay is moved by its insets
   instead: a translate would make it the containing block of the map's fixed
   close button, which would then scroll away with the map. */
:root { --viewport-slip-top: 0px; --viewport-slip-bottom: 0px; }
header,
.toast-container,
.ptr-indicator,
.expo-show-head,
.show-title-filter,
.rings-sticky,
.rings-sticky ~ .schedule-ring-tables .schedule-ring-table > h2,
.rings-sticky ~ .schedule-own-view > .schedule-own-head,
.translation-letter h2 { translate: 0 var(--viewport-slip-top); }
.bar-nav,
.consent-bar,
.notify-saving,
.reorder-panel,
.offline-banner,
.bulk-fab-container { translate: 0 var(--viewport-slip-bottom); }

/* Toast Notifications */
.toast-container {
    position: fixed;
    top: 24px;
    left: 50%;
    transform: translateX(-50%);
    width: 90%;
    max-width: 400px;
    z-index: var(--z-notice);
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
}

.toast {
    background-color: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    padding: 1rem 1.25rem;
    box-shadow: 0 20px 40px rgba(0,0,0,0.8);
    display: flex;
    align-items: flex-start;
    gap: 0.875rem;
    position: relative;
    animation: slide-down 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
    transition: opacity 0.3s ease, transform 0.3s ease;
}

@keyframes slide-down {
    from {
        opacity: 0;
        transform: translateY(-20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.toast-error {
    border-left: 4px solid var(--color-my-dogs);
    border-color: rgba(var(--color-my-dogs-rgb), 0.3) rgba(var(--color-my-dogs-rgb), 0.3) rgba(var(--color-my-dogs-rgb), 0.3) var(--color-my-dogs);
}

.toast-success {
    border-left: 4px solid var(--color-friends);
    border-color: rgba(var(--color-friends-rgb), 0.3) rgba(var(--color-friends-rgb), 0.3) rgba(var(--color-friends-rgb), 0.3) var(--color-friends);
}

.toast-icon {
    font-size: 1.25rem;
    line-height: 1;
    margin-top: 2px;
}

.toast-content {
    flex: 1;
}

.toast-title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.95rem;
    margin-bottom: 2px;
}

.toast-message {
    font-size: 0.85rem;
    color: var(--text-secondary);
    line-height: 1.4;
}

.toast-close {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 1.2rem;
    cursor: pointer;
    line-height: 1;
    transition: var(--transition-premium);
}

.toast-close:hover {
    color: var(--text-primary);
}

/* Modal System */
.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    /* The dialog scrolls inside the overlay, and the scroll stops there: a
       gesture that runs past its end must not be handed to the page behind. */
    overflow: auto;
    overscroll-behavior: contain;
    padding: 0.75rem;
    background-color: rgba(var(--bg-base-rgb), 0.8);
    backdrop-filter: blur(12px);
    z-index: var(--z-modal);
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
/* Moved by its insets, not a translate: see the viewport slip block above. */
.modal-overlay { bottom: calc(-1 * var(--viewport-slip-bottom)); top: var(--viewport-slip-bottom); }

.modal-overlay.active {
    opacity: 1;
    pointer-events: auto;
}

.modal-container {
    background-color: var(--bg-surface);
    border: 1px solid var(--border-highlight);
    border-radius: var(--radius-lg);
    width: 90%;
    max-width: min(520px, calc(100vw - 24px));
    /* A flex item refuses to shrink below its content's min-content width
       unless it is told to. The ring picker's <select> is as wide as its
       longest breed name, so on a phone the dialog grew past the screen and
       the page could be dragged sideways behind it. */
    min-width: 0;
    box-shadow: var(--shadow-premium), 0 30px 60px -15px rgba(0, 0, 0, 0.9);
    transform: scale(0.92) translateY(10px);
    transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
    overflow: hidden;
    /* A dialog that grows -- the year grid opening, a long form -- stops at the
       viewport and scrolls its body, instead of running off both edges where
       overflow: hidden puts it out of reach. */
    display: flex;
    flex-direction: column;
    max-height: 90vh;
}

.modal-overlay.active .modal-container {
    transform: scale(1) translateY(0);
}

.modal-header {
    padding: 1.125rem 1.5rem;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-shrink: 0;
}

.modal-title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.15rem;
    letter-spacing: -0.01em;
    color: var(--text-primary);
}

.breed-lists-title { line-height: 1; }
.breed-lists-title-name { cursor: pointer; }
.breed-lists-rename-toggle {
    background: none;
    border: 0;
    color: var(--text-secondary);
    cursor: pointer;
    display: inline-block;
    font-size: inherit;
    line-height: 0;
    margin-left: 0.375rem;
    padding: 0;
    vertical-align: -0.08em;
}
.breed-lists-rename-toggle:hover, .breed-lists-rename-toggle[aria-expanded="true"] { color: var(--accent-primary); }
.breed-lists-rename-toggle .action-icon { height: 1em; width: 1em; }
.breed-lists-rename { margin-bottom: 1.25rem; }
.breed-lists-rename-save { margin-top: 0.75rem; }
.breed-lists-rename small { color: var(--text-muted); display: block; margin-top: 0.375rem; }

.modal-close {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 1.6rem;
    cursor: pointer;
    line-height: 1;
    transition: var(--transition-premium);
    padding: 0.25rem;
}

.modal-close:hover {
    color: var(--color-my-dogs);
}

.modal-body {
    padding: 1.5rem;
    overflow-y: auto;
    min-width: 0;
}

/* Same story one level down: a long option must not set the dialog's width. */
.modal-body select.input-field {
    max-width: 100%;
    text-overflow: ellipsis;
}

/* While a dialog is open the page behind it does not scroll — in either
   direction. Without this the document keeps its own scroll under a fixed
   overlay, which on a phone reads as the screen sliding about by itself. */
body.modal-open {
    overflow: hidden;
}

/* Shows Page Layout Styles */
.show-card-layout {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
}

/* The mark in front of a name: a green tick on a show that has run, a grey
   clock on one ahead without a timetable, nothing otherwise (DIM-787). */
.show-card-mark { align-items: center; display: inline-flex; flex: 0 0 auto; justify-content: center; transform: translateY(2px); }
.show-card-mark-icon { display: block; height: 17px; width: 17px; }
.show-card-mark-done { color: var(--color-friends); }
.show-card-mark-waiting { color: var(--text-secondary); }

/* The name's line: the mark, the name, a badge or the dates beside it, the
   settings cog. baseline alignment keeps them sitting with the type. */
.show-card-heading {
    align-items: baseline;
    display: flex;
    /* The dashboard pill puts an "on now" badge and the dates on this line
       beside the name, so it has to be able to take a second row on a phone. */
    flex-wrap: wrap;
    gap: 0 0.4375rem;
}


/* The show running today. The block only exists on those days, so it is the
   one thing on the page worth pointing at. The dashboard's show bar wears the
   same tint on the same days, so the two pages say "this one is on" alike. */
.show-section-now .section-header {
    color: var(--accent-primary);
}

.show-section-now .show-card,
.active-show-bar.active-show-bar-now {
    border: 1px solid rgba(var(--accent-primary-rgb), .45);
    background: linear-gradient(135deg, rgba(var(--accent-primary-rgb), .1) 0%, var(--bg-surface) 60%);
}

#company_field {
    position: absolute;
    left: -5000px;
}
/* The past block is folded away above the rest of the page. Its own header
   scrolls off when it opens, so the toggle lives at the bottom, where it keeps
   its place on screen. */
.folded-section-toggle {
    align-items: center;
    background: none;
    border: 1px dashed var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-muted);
    cursor: pointer;
    display: flex;
    font: 700 .72rem var(--font-display);
    gap: 0.5rem;
    justify-content: center;
    letter-spacing: .06em;
    margin: 16px 0 4px;
    padding: 0.625rem 0.875rem;
    text-transform: uppercase;
    width: 100%;
}

.folded-section-toggle:hover {
    border-color: rgba(var(--accent-primary-rgb), .5);
    color: var(--accent-primary);
}

/* Tags on a show card: what is missing, and what is still open. Wrapped so a
   card can carry both without either being pushed off the edge. */
.show-card-tags { display: flex; flex-wrap: wrap; gap: 0.375rem; }

/* The titles a show awards, coloured as cpc.pt colours them (DIM-789). */
.show-card-title {
    border: 1px solid;
    border-radius: 6px;
    display: inline-flex;
    font: 700 .66rem var(--font-display);
    letter-spacing: .02em;
    margin-top: 4px;
    padding: 0.1875rem 0.5rem;
    white-space: nowrap;
}
.show-card-title-cac { background: rgba(var(--color-friends-rgb), .12); border-color: rgba(var(--color-friends-rgb), .4); color: var(--color-friends); }
.show-card-title-cacib { background: rgba(var(--color-orders-rgb), .12); border-color: rgba(var(--color-orders-rgb), .45); color: var(--color-orders); }
.show-card-title-special { background: rgba(176, 96, 64, .14); border-color: rgba(176, 96, 64, .5); color: #c9805f; }

.show-card-tag {
    background: rgba(var(--color-my-dogs-rgb), .1);
    border: 1px solid rgba(var(--color-my-dogs-rgb), .3);
    border-radius: 999px;
    color: var(--color-my-dogs);
    display: inline-flex;
    font: 700 .66rem var(--font-display);
    letter-spacing: .03em;
    margin-top: 4px;
    padding: 0.1875rem 0.5625rem;
    white-space: nowrap;
}

/* Entries still open is the one piece of good news a card carries, so it is the
   one tag painted in the "go" colour rather than the warning one.

   After the base rule, not before it. Same specificity, so source order decides,
   and while this sat above .show-card-tag the base rule's `border` shorthand and
   `color` won and the tag came out in the warning colour. Invisible for as long
   as the tag itself was: it only ever appeared for three days after an import,
   so nobody was looking at a green that was not green. */
.show-card-tag-open {
    background: rgba(var(--color-friends-rgb), .12);
    border-color: rgba(var(--color-friends-rgb), .35);
    color: var(--color-friends);
}

/* The state tag stands under the date or the countdown, on the right (DIM-799). */
.show-card-date .show-card-tag,
.active-show-countdown .show-card-tag { align-self: flex-end; margin-top: 0.375rem; }

/* The filter by title above the shows list (DIM-799). */
.show-title-filter { align-items: center; display: flex; flex-wrap: wrap; gap: 0.375rem; margin: 0 0 1rem; }
/* It stays under the header while the list scrolls (Dimas, 2026-10-20), on the
   page's own background so the cards pass under it, as the rings bar does. */
.show-title-filter { background: var(--bg-base); padding-bottom: 0.5rem; padding-top: 0.5rem; position: sticky; top: var(--header-height); z-index: var(--z-content); }
.show-title-filter-chip {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    color: var(--text-secondary);
    cursor: pointer;
    font: 700 .68rem var(--font-display);
    letter-spacing: .02em;
    min-height: 1.75rem;
    padding: 0.25rem 0.625rem; /* tighter: the row of titles took too much room (Dimas, 2026-10-20) */
    white-space: nowrap;
}
.show-title-filter-chip:hover { border-color: rgba(var(--accent-primary-rgb), .5); color: var(--text-primary); }
.show-title-filter-chip[aria-pressed="true"] { background: var(--accent-primary); border-color: var(--accent-primary); color: #fff; }
.show-title-filter-chip:focus-visible, .show-title-filter-clear:focus-visible { outline: 2px solid var(--accent-primary); outline-offset: 2px; }
.show-title-filter-clear { background: none; border: 0; color: var(--accent-primary); cursor: pointer; font: 600 .78rem var(--font-body); padding: 0.375rem 0.25rem; }
.show-title-filter-clear[hidden], .show-card[hidden], .show-year-heading[hidden], .folded-section-toggle[hidden], .show-title-filter-empty[hidden] { display: none; }
.show-title-filter-empty { color: var(--text-muted); font-size: .85rem; margin: 0.5rem 0 1rem; }
/* On a phone the chips are one row that scrolls sideways: wrapped, six titles
   took three rows and pushed the first show half a screen down. */
@media (max-width: 600px) {
    .show-title-filter { flex-wrap: nowrap; margin-left: -1rem; margin-right: -1rem; overflow-x: auto; padding: 0.5rem 1rem; scrollbar-width: none; }
    .show-title-filter::-webkit-scrollbar { display: none; }
    .show-title-filter > * { flex-shrink: 0; }
}

.show-card-info {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

/* line-height 1: a show name is one line of display type sitting directly above
   its venue, and the font's own leading opened a gap that read as a paragraph
   break inside a single card. A name long enough to wrap still wraps. */
.show-card-name {
    color: var(--text-primary);
    display: inline-block;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: -0.01em;
    line-height: 1;
    text-decoration: none;
    transition: var(--transition-premium);
}

.show-card-place {
    align-items: baseline;
    color: var(--text-secondary);
    display: flex;
    font-size: 0.8rem;
    line-height: 1.2;
    margin: 4px 0 6px;
}

/* A show with nothing to open is paler than one you can, so the list says at
   a glance which names lead somewhere (Dimas, 2026-10-20, DIM-787). */
span.show-card-name { color: var(--text-unlinked); }
/* The steward's own show is the page they are on, not a show they cannot open. */
.assistant-sheet-head span.show-card-name { color: var(--text-primary); }

/* A show with no schedule is not a link — there is nothing behind it yet — so
   only the anchor answers to hover. */
a.show-card-name:hover {
    color: var(--accent-primary);
}

.show-card-actions {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.show-card-actions .btn-premium {
    width: auto;
    padding: 0.5rem 1rem;
    font-size: 0.8rem;
}

/* The days on one line, the year under them. "28 Feb - 1 Mar 2026" on one line
   either wrapped wherever it liked or pushed the name; and the days are what a
   reader is after, the year only what tells two Bejas apart. */
.show-card-date {
    display: flex;
    flex-direction: column;
    text-align: right;
}

.show-card-days {
    color: var(--accent-primary);
    font: 700 0.9rem/1.1 var(--font-display);
    white-space: nowrap;
}

.show-card-year {
    color: var(--text-muted);
    font: 600 0.74rem/1.2 var(--font-display);
    letter-spacing: .04em;
    white-space: nowrap;
}

/* Schedule views: imported table and ring-by-ring day board */
.schedule-heading {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 1rem;
    margin: 0 0 10px;
}

/* Root's link from a show to its card in Settings → Expositions. */
.show-settings-link {
    align-items: center;
    color: var(--accent-primary);
    display: inline-flex;
    flex: 0 0 auto;
    font: 700 0.72rem/1 var(--font-display);
    gap: 0.375rem;
    letter-spacing: 0.04em;
    text-decoration: none;
}
.show-settings-link:hover { opacity: 0.8; }
.show-settings-link .action-icon { height: 16px; width: 16px; }
.show-settings-link-icon { margin-left: 0.25rem; vertical-align: middle; }

.schedule-heading h1 {
    font: 800 clamp(1.45rem, 4vw, 2rem)/1.15 var(--font-display);
    letter-spacing: -0.035em;
}

/* The title and the venue map button share one row, the button pressed to the
   right edge, on every width (DIM-778). */
.schedule-heading-main { flex: 1 1 auto; min-width: 0; }
.schedule-title-row { align-items: center; display: flex; gap: 0.75rem; justify-content: space-between; }
.schedule-title-row h1 { min-width: 0; overflow-wrap: anywhere; }
.show-map-button {
    align-items: center;
    background: var(--bg-surface);
    border: 1px solid var(--border-highlight);
    border-radius: var(--radius-md, 10px);
    color: var(--text-primary);
    cursor: pointer;
    display: inline-flex;
    flex: 0 0 auto;
    font: 700 0.78rem/1 var(--font-display);
    gap: 0.4rem;
    padding: 0.5rem 0.75rem;
}
.show-map-button:hover { border-color: var(--accent-primary); color: var(--accent-primary); }
.show-map-button .action-icon { height: 18px; width: 18px; }

/* The map itself: the whole screen, the picture as large as it fits, one
   Close button. A map larger than the screen scrolls inside the frame. */
.show-map-modal { flex-direction: column; gap: 0.75rem; padding: 4rem 0.75rem 0.75rem; } /* the top keeps the × off the map */
.show-map-frame {
    align-items: center;
    display: flex;
    flex: 1 1 auto;
    justify-content: center;
    min-height: 0;
    overflow: auto;
    width: 100%;
}
.show-map-image {
    background: #fff;
    border-radius: var(--radius-md, 10px);
    display: block;
    height: auto;
    max-height: calc(100vh - 8.75rem);
    max-height: calc(100dvh - 8.75rem);
    max-width: 100%;
    object-fit: contain;
    width: auto;
}
.show-map-close { flex: 0 0 auto; min-width: 9rem; }
.modal-overlay .show-map-x {
    align-items: center;
    background-color: var(--accent-primary);
    border: none;
    border-radius: var(--radius-sm);
    box-shadow: 0 4px 15px rgba(var(--accent-primary-rgb), 0.35);
    color: white;
    display: inline-flex;
    font-size: 1.9rem;
    height: 2.75rem;
    justify-content: center;
    line-height: 1;
    padding: 0 0 0.15rem;
    position: fixed;
    right: 0.75rem;
    top: 0.75rem;
    width: 2.75rem;
    z-index: 2;
}
.modal-overlay .show-map-x:hover { color: white; filter: brightness(1.1); }
/* Root's settings link shares the subtitle's row, pressed to the right. */
.schedule-subtitle-row { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.25rem 1rem; justify-content: space-between; }

.schedule-subtitle { color: var(--text-secondary); font-size: 0.84rem; margin-top: 6px; }
.schedule-subtitle a { color: inherit; text-decoration: underline dotted; text-underline-offset: 3px; }
.changes-day { margin-top: 1.25rem; scroll-margin-top: 1rem; }
.changes-day-title { font-size: 1rem; margin: 0 0 0.5rem; }
.changes-head { font-weight: 600; margin-top: 0.75rem; overflow-wrap: anywhere; }
.changes-head:first-child { margin-top: 0; }
.changes-list { margin: 0.25rem 0 0; overflow-wrap: anywhere; padding-left: 1.125rem; }

.schedule-view-switch {
    display: flex;
    padding: 0.25rem;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    flex-shrink: 0;
}

.schedule-view-option, .schedule-date-tab {
    color: var(--text-secondary);
    text-decoration: none;
    font: 700 0.78rem var(--font-display);
    transition: var(--transition-premium);
}

.schedule-view-option { padding: 0.4375rem 0.625rem; border-radius: 6px; }
.schedule-view-option.active { color: #fff; background: var(--accent-primary); }
/* The same switch made of buttons (the catalogue's Males / Females, DIM-728):
   without this the browser's own button border and background show through. */
button.schedule-view-option { border: 0; background: none; cursor: pointer; line-height: inherit; }
button.schedule-view-option.active { background: var(--accent-primary); }

/* One row: the day switcher on the left, the view switcher on the right. */
.schedule-tools { align-items: center; display: flex; flex-wrap: nowrap; gap: 0.75rem; justify-content: space-between; margin-bottom: 20px; }
.schedule-tools .schedule-view-switch { flex: 0 0 auto; margin-left: auto; }
.schedule-date-tabs { display: flex; flex: 0 1 auto; gap: 0.5rem; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.schedule-date-tabs::-webkit-scrollbar { display: none; }
.schedule-date-tab { min-width: 55px; padding: 0.5rem 0.75rem; text-align: center; background: var(--bg-surface); border: 1px solid var(--border-color); border-radius: 10px; }
.schedule-date-tab span { display: block; font-size: 0.68rem; text-transform: uppercase; }
.schedule-date-tab strong { display: block; color: var(--text-primary); font-size: 1rem; }
.schedule-date-tab.active { border-color: var(--accent-primary); background: var(--accent-glow); color: var(--accent-primary); }
.schedule-date-tab.active span { color: var(--bg-base); }

.schedule-ring-filter { display: grid; gap: 0.375rem; grid-auto-columns: 1fr; grid-auto-flow: column; margin-bottom: 8px; width: 100%; }
.schedule-ring-filter-btn { align-items: center; background: var(--bg-surface); border: 1px solid var(--border-color); border-radius: 8px; color: var(--text-secondary); cursor: pointer; display: inline-flex; font: 700 .78rem var(--font-display); justify-content: center; overflow: hidden; padding: 0.375rem 0.25rem; transition: var(--transition-premium); white-space: nowrap; }
.schedule-ring-filter-btn .ring-word { margin-right: 5px; opacity: .5; } /* "Ring" / "R" recede, the number reads (Dimas, 2026-10-19) */
/* Short of room the gap goes, then the word with it (DIM-786). */
.schedule-ring-filter.is-tight .ring-word { margin-right: 0; }
.schedule-ring-filter-btn .ring-word:empty { display: none; }
.schedule-ring-filter-btn:hover { border-color: var(--accent-primary); color: var(--accent-primary); }
.schedule-ring-filter-btn.active { background: var(--accent-primary); border-color: var(--accent-primary); color: #fff; }
.schedule-ring-filter-btn.past { opacity: .4; }
/* Class names are longer than ring numbers. One row of full names; when that
   does not fit, one row of short ones (is-short, set by fitClassLabels() the
   way "Ring" becomes "R"); only when even those do not fit, two rows. */
.catalogue-class-short { display: none; }
.catalogue-class-filter.is-short .catalogue-class-full { display: none; }
.catalogue-class-filter.is-short .catalogue-class-short { display: inline; }
.catalogue-class-filter.is-short { gap: 0.25rem; }
.catalogue-class-filter.is-short .schedule-ring-filter-btn { padding-left: 0.125rem; padding-right: 0.125rem; }
/* Two even rows: fitClassLabels() sets the column count to half the buttons. */
.catalogue-class-filter.is-wrapped { grid-auto-flow: row; }
/* Each filter row of the catalogue in its own frame, like the Males / Females
   switch, so rings and classes read as two choices and not one block. */
.catalogue-filter-frame { box-sizing: border-box; padding: 0.25rem; background: var(--bg-card); border: 1px solid var(--border-color); border-radius: 10px; margin-bottom: 0.625rem; }

/* Free-text quick search sitting right under the ring row. */
.schedule-search { margin-bottom: 20px; position: relative; width: 100%; }
.schedule-search-input { background: var(--bg-input); border: 1px solid var(--border-input); border-radius: 8px; color: var(--text-primary); font: 500 .85rem var(--font-body); padding: 0.5625rem 2.125rem 0.5625rem 0.75rem; transition: var(--transition-premium); width: 100%; }
.schedule-search-input::placeholder { color: var(--text-muted); }
.schedule-search-input:focus { border-color: var(--accent-primary); outline: none; }
.schedule-search-input::-webkit-search-cancel-button { display: none; }
/* iOS Safari zooms the page into any field whose text is under 16px, and the
   layout jumps. On touch screens every field is 16px; pinch-zoom stays
   available, which maximum-scale=1 would take away on Android. */
@media (hover: none) and (pointer: coarse) {
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]), select, textarea { font-size: 16px !important; }
}
.schedule-search-clear { background: none; border: 0; color: var(--text-muted); cursor: pointer; font: 700 1.1rem/1 var(--font-display); padding: 0.25rem 0.5rem; position: absolute; right: 4px; top: 50%; transform: translateY(-50%); }
.schedule-search-clear:hover { color: var(--accent-primary); }
.schedule-search-empty { color: var(--text-secondary); font-size: .85rem; margin: 0 0 20px; text-align: center; }
.is-filtered-out { display: none !important; }

.schedule-ring-tables { display: grid; gap: 1.625rem; }
.schedule-ring-table { min-width: 0; }
/* Two rings side by side once the wider container has room (Dimas, 2026-10-23).
   The by-group view keeps one column: its tables mix rings and run long. */
@media (min-width: 960px) {
    .schedule-ring-tables:not(.schedule-group-tables) { align-items: start; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.schedule-ring-table h2 { align-items: baseline; color: var(--text-primary); display: flex; flex-wrap: wrap; font: 800 1.05rem var(--font-display); gap: 0.25rem 0.625rem; margin: 0 0 10px; }
.schedule-ring-table h2 small { color: var(--text-secondary); font: 600 .82rem var(--font-display); }
.schedule-judge-link { text-decoration: none; }
.schedule-judge-link:hover { text-decoration: underline; }
.schedule-table-wrap { overflow-x: auto; border: 1px solid var(--border-color); border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: var(--shadow-premium); }
/* Fixed layout, or every ring table sizes its columns to its own longest breed
   and the day reads as a pile of unrelated tables instead of one list. */
.schedule-table { width: 100%; border-collapse: collapse; table-layout: fixed; text-align: left; }
.schedule-table th:first-child, .schedule-table td:first-child { width: max(84px, 5.2rem); }
.schedule-table th:last-child, .schedule-table td:last-child { width: 76px; }
/* The catalogue view (DIM-715): a class on the left, its numbers on the right,
   wrapping as many lines as a big class needs. */
.catalogue-view-exposition { margin: 0 0 -0.75rem; color: var(--text-secondary); font-size: .9rem; }
.catalogue-view-exposition strong { color: var(--text-primary); }
.catalogue-table td:first-child { width: 46%; }
.catalogue-table td:last-child { width: auto; }
.catalogue-table td { vertical-align: top; padding-top: 0.375rem; padding-bottom: 0.375rem; }
.catalogue-numbers { color: var(--text-primary); font-variant-numeric: tabular-nums; word-spacing: 0.35em; }
/* The catalogue page (DIM-728): a class heading, then one row per dog — its
   number on the left, its name and what the catalogue says of it on the right. */
.catalogue-group { display: contents; }
/* Three day tabs and three groupings do not fit one phone line: they wrap,
   rather than squeezing the days into a strip that scrolls. The dog table is
   laid out automatically: fixed layout took its widths from the class heading
   that spans both columns and gave the number half the row. */
.catalogue-tools { flex-wrap: wrap; }
/* Folded breeds: the heading is the button, the dogs show when it is open or
   when a search matched inside it. */
.catalogue-breed:not(.is-open):not(.is-searching) .catalogue-breed-body { display: none; }
.catalogue-breed h2 { margin: 0; }
.catalogue-breed-toggle { all: unset; box-sizing: border-box; cursor: pointer; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.5rem; width: 100%; padding: 0.25rem 0; font: inherit; color: inherit; }
.catalogue-breed-toggle::before { content: '▸'; color: var(--text-muted); transition: transform .15s; display: inline-block; }
.catalogue-breed.is-open .catalogue-breed-toggle::before, .catalogue-breed.is-searching .catalogue-breed-toggle::before { transform: rotate(90deg); }
.catalogue-breed-toggle:focus-visible { outline: 2px solid var(--accent-primary); outline-offset: 2px; border-radius: 4px; }
.catalogue-breed-toggle small { color: var(--text-secondary); font-weight: 400; }
.schedule-table.catalogue-dogs { table-layout: auto; }
.schedule-table.catalogue-dogs .catalogue-class-row th { width: auto; }
.catalogue-group[hidden] { display: none; }
.catalogue-dogs .catalogue-class-row th { padding: 0.5rem 0.75rem 0.25rem; font-size: .72rem; letter-spacing: .03em; text-transform: uppercase; color: var(--text-muted); background: var(--bg-elevated, transparent); text-align: left; }
.catalogue-dogs td { vertical-align: top; padding-top: 0.375rem; padding-bottom: 0.375rem; }
.schedule-table.catalogue-dogs td.catalogue-dog-no { width: 1%; white-space: nowrap; padding-right: 0.75rem; font-variant-numeric: tabular-nums; font-weight: 700; color: var(--text-primary); }
.schedule-table.catalogue-dogs td.catalogue-dog { width: auto; }
.catalogue-dog-name { display: block; color: var(--text-primary); font-weight: 600; overflow-wrap: anywhere; }
.catalogue-dog-meta { display: block; color: var(--text-secondary); font-size: .8rem; overflow-wrap: anywhere; }
.catalogue-dog-people { color: var(--text-muted); }
/* Titles as tags (DIM-730). Every tag looks the same, whether or not we know
   what it stands for (Dimas, 2026-10-12); only a known one opens its meaning. */
.catalogue-titles { display: flex; flex-wrap: wrap; gap: 0.25rem; margin: 0.25rem 0 0.125rem; }
.catalogue-title { all: unset; box-sizing: border-box; display: inline-block; padding: 0.0625rem 0.375rem; border: 1px solid var(--border-color); border-radius: 999px; font-size: .7rem; font-weight: 600; line-height: 1.5; color: var(--accent-primary); border-color: var(--accent-primary); font-variant-numeric: tabular-nums; white-space: nowrap; }
button.catalogue-title { cursor: pointer; }
button.catalogue-title:focus-visible { outline: 2px solid var(--accent-primary); outline-offset: 1px; }
.catalogue-title-explain { display: block; color: var(--text-secondary); font-size: .78rem; margin-top: 0.125rem; }
.catalogue-title-explain[hidden] { display: none; }

.schedule-table th {
    padding: 0.5rem 0.5rem;
    font-size: .64rem;
    letter-spacing: .03em;
    color: var(--text-muted);
    text-transform: uppercase;
    background: var(--bg-card);
}
/* A fixed column is a promise the header has to keep. "Собаки" set wide and
   spaced is 64px of min-content against a 58px column, and the table pushed
   the extra six pixels out sideways: wrapping is allowed here so no
   translation of a heading can ever hand the table a horizontal scrollbar. */
.schedule-table th { overflow-wrap: anywhere; }
.schedule-table td { padding: 0.1875rem 0.5rem; border-top: 1px solid var(--border-color); color: var(--text-secondary); font-size: .86rem; }
@media (hover: hover) { .schedule-table tr:hover td { background: var(--tint-subtle); } }
.schedule-table tr.past td { opacity: .4; }
/* The row in the ring says so by being lit, not by wearing a tag. A badge on
   the row competed with the breed name for the same glance; the colour of the
   row is read before either of them. */
.schedule-table tr.now td { background: rgba(var(--accent-primary-rgb), .12); }
.schedule-table tr.now td:first-child { box-shadow: inset 3px 0 0 var(--accent-primary); }
.schedule-now-badge { background: var(--accent-primary); color: var(--bg-base); font-size: 0.65rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; padding: 0.125rem 0.375rem; border-radius: 4px; margin-left: 8px; display: inline-block; vertical-align: middle; line-height: 1; }
/* The same badge, paler: a breed still to come says how long, and must not
   compete with the one that is actually in the ring. */
.schedule-now-badge.is-ahead {
    background: rgba(var(--accent-primary-rgb), .22);
    color: var(--text-secondary);
    /* "+1h23m" is a reading, not a label: upper case mangles the h and the m. */
    text-transform: none;
}

.schedule-next-badge { background: transparent; color: var(--text-muted); border: 1px solid var(--border-color); font-size: 0.65rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; padding: 0.0625rem 0.3125rem; border-radius: 4px; margin-left: 8px; display: inline-block; vertical-align: middle; line-height: 1; }
.schedule-table-time { color: var(--accent-primary) !important; font: 800 .95rem var(--font-display); white-space: nowrap; }
.schedule-table-breed { color: var(--text-primary) !important; font: 600 .95rem var(--font-display); word-wrap: break-word; word-break: break-word; white-space: normal; }

@media (max-width: 500px) {
    .schedule-table th {
        padding: 0.5rem 0.5rem;
        font-size: .64rem;
        letter-spacing: .03em;
    }
    .schedule-table th:first-child, .schedule-table td:first-child {width: max(62px, 4rem); padding: 0.1875rem 0.1875rem 0.1875rem 0.5rem; }
    .schedule-table th:last-child, .schedule-table td:last-child { width: 66px; }
}

.schedule-empty-state { margin-top: 32px; text-align: center; }

@media (max-width: 560px) {
    .schedule-heading { align-items: flex-start; flex-direction: column; }
    .schedule-heading-main { align-self: stretch; }
    .schedule-tools { gap: 0.5rem; }
    .schedule-date-tab { min-width: 46px; padding: 0.4375rem 0.5625rem; }
    .schedule-view-option { padding: 0.4375rem 0.5rem; }
    .bar-tab { padding: 0.3125rem 0.1875rem 0.375rem; font-size: .62rem; }
    .bar-tab-hub { height: 64px; margin: -30px 0.375rem 0; padding: 0; width: 64px; }
}

.import-show-preview {
    background-color: var(--tint-subtle);
    border: 1px solid var(--border-color);
    padding: 0.75rem;
    border-radius: var(--radius-sm);
    margin-bottom: 12px;
}

.import-show-preview-label {
    font-size: 0.8rem;
    color: var(--text-secondary);
    text-transform: uppercase;
    font-weight: bold;
    letter-spacing: 0.05em;
}

.import-show-preview-name {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.05rem;
    margin-top: 4px;
    color: var(--accent-primary);
}

/* Import Tabs */
.import-tabs {
    display: flex;
    gap: 0.25rem;
    margin-bottom: 16px;
    background-color: var(--bg-card);
    border-radius: var(--radius-sm);
    padding: 0.25rem;
    border: 1px solid var(--accent-glow)
}

.import-tab {
    flex: 1;
    padding: 0.625rem 0.75rem;
    border: none;
    background: none;
    color: var(--text-secondary);
    font-family: var(--font-body);
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    border-radius: 6px;
    transition: var(--transition-premium);
}

.import-tab:hover {
    color: var(--text-primary);
    background-color: var(--bg-overlay);
}

.import-tab.active {
    background-color: var(--accent-primary);
    color: white;
}

/* Settings → Usage: the tab bar is links and scrolls sideways inside itself */
.usage-tabs { flex-wrap: wrap; }
@media (max-width: 767px) {
    /* On a phone one row that scrolls sideways, without the scrollbar. */
    .usage-tabs { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
    .usage-tabs::-webkit-scrollbar { display: none; }
}
.usage-tabs .import-tab { flex: 0 0 auto; text-align: center; text-decoration: none; white-space: nowrap; }
.usage-panel[hidden] { display: none; }

/* Import Panels */
.import-panel {
    display: none;
}

.import-panel.active {
    display: block;
}

/* Ring correction dialog: the three answers and the buttons under them */
.ring-update-answers {
    margin-top: 1rem;
}

.ring-update-answers .import-tabs {
    margin-bottom: 0.75rem;
}

.ring-update-save {
    margin-top: 1.5rem;
}

/* Import Hints */
.import-field-hint {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-weight: normal;
    display: block;
    margin-top: 4px;
    margin-bottom: 8px;
    line-height: 1.5;
}

/* Import Result Feedback */
.import-result {
    margin-top: 12px;
    padding: 0;
    font-size: 0.85rem;
    border-radius: var(--radius-sm);
    transition: var(--transition-premium);
}

.import-result:empty {
    display: none;
}

/* Pre-import page checks: what the page must contain, and what it does. */
.import-note { font-size: .74rem; margin-top: 8px; opacity: .85; word-break: break-all; }
.import-problems { display: grid; gap: 0.3125rem; font-size: .78rem; list-style: none; margin: 10px 0 0; padding: 0; }
.import-problems li { padding-left: 1rem; position: relative; }
.import-problems li::before { content: "•"; left: 3px; position: absolute; }
.import-checks ul { display: grid; gap: 0.25rem; list-style: none; margin: 8px 0 0; padding: 0; }
.import-checks li { align-items: baseline; display: flex; font-size: .72rem; gap: 0.5rem; justify-content: space-between; }
.import-checks li small { color: var(--text-muted); flex: 0 0 auto; }
.import-checks .check-ok { color: var(--color-friends); }
.import-checks .check-fail { color: var(--color-my-dogs); }

/* Root-only diagnostics, shown under an error toast or an import result. */
.import-detail, .toast-detail { margin-top: 8px; }
.import-detail summary, .toast-detail summary { cursor: pointer; font: 700 .68rem var(--font-display); letter-spacing: .06em; opacity: .8; text-transform: uppercase; }
.import-detail pre, .toast-detail pre {
    background: rgba(0,0,0,.28);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    color: var(--text-secondary);
    font-size: .7rem;
    line-height: 1.45;
    margin-top: 6px;
    max-height: 220px;
    overflow: auto;
    padding: 0.5rem 0.625rem;
    white-space: pre-wrap;
    word-break: break-word;
}

.import-result-success {
    padding: 0.75rem;
    background-color: rgba(var(--color-friends-rgb), 0.1);
    border: 1px solid rgba(var(--color-friends-rgb), 0.3);
    color: var(--color-friends);
}

.import-result-error {
    padding: 0.75rem;
    background-color: rgba(var(--color-my-dogs-rgb), 0.1);
    border: 1px solid rgba(var(--color-my-dogs-rgb), 0.3);
    color: var(--color-my-dogs);
}
button.link-button {
    appearance: none;
    border: 0;
    padding: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    text-decoration: underline;
    cursor: pointer;
}

/* Breed CRUD specific styles */
.breed-search-card {
    padding: 0.75rem 1rem;
    margin-bottom: 16px;
}
.breed-search-input {
    width: 100%;
    padding: 0.625rem 0.875rem;
    background: var(--bg-base);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font: inherit;
    font-size: 0.9rem;
    transition: var(--transition-premium);
}
.breed-search-input:focus {
    border-color: var(--accent-primary);
    outline: none;
    box-shadow: 0 0 0 2px rgba(var(--accent-primary-rgb), 0.2);
}
/* Name and actions only: two columns need no horizontal scroll floor. */
#breeds-table { min-width: 0; }
#breeds-table td.user-actions, #breeds-table th:last-child { width: 1%; }
.breed-edit-layout {
    display: grid;
    gap: 1rem;
    grid-template-columns: minmax(0, 1fr) minmax(280px, 0.85fr);
    align-items: start;
}
/* Same reason as the track above: a grid item defaults to a min-content floor,
   so any card holding something wide would widen the page instead of scrolling
   or wrapping inside itself. */
.breed-edit-layout > * { min-width: 0; }
/* Every name the breed answers to, in one list: the catalogue's own first, then
   the aliases. Each row is a button because each row opens an editor, and a
   thing you click is a control whether or not it looks like one. */
.breed-name-list {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin-top: 16px;
}
.breed-name-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    width: 100%;
    padding: 0.625rem 0.75rem;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--bg-card);
    color: var(--text-primary);
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.breed-name-item:hover { border-color: var(--accent-primary); }
.breed-name-item-text { min-width: 0; overflow-wrap: anywhere; font-size: .85rem; }
.breed-name-item-main .breed-name-item-text { font-weight: 700; }
.breed-name-item-tags {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    gap: 0.5rem;
}
.breed-name-item-tags small { font-size: .7rem; color: var(--text-secondary); }
/* The two things a name can have done to it that are not a save, side by side
   under the form: each is its own submission, so each is its own form. */
.breed-name-modal-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.625rem;
    margin-top: 16px;
    padding-top: 0.875rem;
    border-top: 1px solid var(--border-color);
}
.breed-name-modal-actions .btn-premium { width: auto; font-size: .72rem; padding: 0.5625rem 0.8125rem; }
/* The one name that is the breed rather than a way of finding it. */
.breed-name-badge {
    padding: 0.125rem 0.5rem;
    border-radius: 4px;
    background: var(--accent-glow);
    color: var(--bg-card);
    font-size: .66rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
}
/* Aliases are added through a modal, so the card header carries the button. */
.breed-alias-card-head {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    justify-content: space-between;
}
.breed-alias-card-head .settings-card-title { margin-bottom: 0; }
.breed-alias-card-head .btn-premium { font-size: .72rem; padding: 0.5625rem 0.8125rem; white-space: nowrap; width: auto; }
.alias-lang {
    background: var(--bg-overlay);
    padding: 0.125rem 0.375rem;
    border-radius: 4px;
    font-size: 0.75rem;
    color: var(--text-secondary);
    text-transform: uppercase;
}
/* Two lines above the catalogue: what the run is doing, and where the
   catalogue stands. The second is permanent, so the block never collapses and
   the table below it does not jump when a fetch starts or ends. */
.fci-run-status { margin-bottom: 12px; }
.fci-run-line { margin: 0; font-size: .78rem; }
.fci-run-line + .fci-run-line { margin-top: 2px; }
.fci-run-line b { color: var(--text-primary); font-weight: 700; }
.fci-run-line[hidden] { display: none; }

/* Catalogue row: a 35px slot, then the name. The slot is always there — with a
   picture, with the paw when the breed has FCI data but no picture, and empty
   when it has neither — so every name in the table starts at the same x. */
.breed-name-cell {
    display: flex;
    align-items: center;
    gap: 0.625rem;
}
/* The tick leads the row in a column of its own, so the heading over the names
   labels the names rather than the checkbox. */
.breed-check, .breed-head-select input {
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
    margin: 0;
    accent-color: var(--accent-primary);
    cursor: pointer;
}
#breeds-table th.breed-head-select, #breeds-table td.breed-cell-select { width: 1%; padding-right: 0; }
/* The picture has its own column, so "Breed Name" stands over the names. */
#breeds-table th.breed-head-thumb, #breeds-table td.breed-cell-thumb { width: 1%; padding-right: 0; }
#breeds-table th.breed-head-group, #breeds-table td.breed-cell-group { width: 1%; white-space: nowrap; }
#breeds-table th.breed-head-std, #breeds-table td.breed-cell-std { width: 1%; white-space: nowrap; }
/* A heading you can click is a button, so it is one — keyboard and all. */
.breed-head-sort button,
.table-head-sort button {
    display: inline-flex;
    align-items: center;
    gap: 0.3125rem;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-transform: inherit;
    letter-spacing: inherit;
    cursor: pointer;
}
.breed-head-sort button:hover,
.table-head-sort button:hover { color: var(--text-primary); }
.breed-sort-arrow,
.table-sort-arrow { font-size: .6rem; color: var(--accent-primary); }
.merge-choice-list {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    max-height: 280px;
    overflow-y: auto;
    margin-bottom: 4px;
}
.merge-choice {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.5625rem 0.6875rem;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--bg-card);
    cursor: pointer;
    font-size: .82rem;
}
.merge-choice:hover { border-color: var(--accent-primary); }
.merge-choice input { width: auto; margin: 0; accent-color: var(--accent-primary); }
.merge-choice:has(input:checked) { border-color: var(--accent-primary); }
.breed-delete-form { margin-top: 16px; padding-top: 0.875rem; border-top: 1px solid var(--border-color); }
.breed-delete-form .btn-premium { width: auto; font-size: .72rem; padding: 0.5625rem 0.8125rem; }
.breed-delete-note { margin-top: 16px; padding-top: 0.875rem; border-top: 1px solid var(--border-color); font-size: .72rem; }
/* The name and its note are one column beside the picture, not siblings of it.
   As flex items of the row they could not shrink below their own text, so a
   long name wrapped underneath the picture instead of beside it — min-width:0
   is what lets the text wrap inside the cell it was given. */
.breed-name-body { min-width: 0; flex: 1 1 auto; }
.breed-name-body strong { overflow-wrap: anywhere; }
.breed-thumb {
    flex: 0 0 auto;
    width: 35px;
    height: 35px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 7px;
    overflow: hidden;
}
/* Not square? Fill the square and crop, rather than letterbox the dog. The paw
   is excluded — it is a placeholder sitting in the slot, not the picture. */
.breed-thumb img:not(.breed-paw) { width: 100%; height: 100%; object-fit: cover; display: block; }
.breed-thumb .breed-paw { display: none; width: 22px; height: 22px; object-fit: contain; }
.breed-thumb-photo { background: var(--bg-overlay); }
.breed-thumb-empty { background: rgba(var(--color-important-rgb), .1); }
.breed-thumb-empty .breed-paw { display: block; }
.breed-fci-note { font-size: .7rem; color: var(--text-secondary); }
/* The group has its own column now, so the tag only has to be a tag. */
.breed-group-tag {
    display: inline-block;
    padding: 0.1875rem 0.5rem;
    border: 1px solid var(--accent-glow);
    border-radius: var(--radius-sm);
    color: var(--accent-glow);
    font-weight: 700;
    font-size: .68rem;
    letter-spacing: .04em;
    white-space: nowrap;
}
.breed-group-tag[hidden] { display: none; }
/* The standard body, in the same shape as the group but quieter: it is the
   same word down most of the column, so it reads as a marker rather than
   competing with the group beside it. Empty until the breed has actually been
   read from that body, so the column shows what is confirmed. */
.breed-std-tag {
    display: inline-block;
    padding: 0.1875rem 0.5rem;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font-weight: 700;
    font-size: .66rem;
    letter-spacing: .04em;
    white-space: nowrap;
}
.breed-std-tag[hidden] { display: none; }
/* How many of the six names the breed carries. Deliberately plain until it is
   complete: a column of green ticks down a mostly-translated catalogue says
   nothing, while the few incomplete rows are what the eye should catch. */
.breed-cell-langs { white-space: nowrap; }
.breed-lang-count {
    display: inline-block;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
    font-size: .78rem;
    font-weight: 600;
}
.breed-lang-count.is-complete { color: var(--text-muted); }
/* English and nothing else -- what a fresh import leaves behind, and the set
   worth running a translation hunt over first. */
.breed-lang-tag {
    display: inline-block;
    margin-left: 6px;
    padding: 0.125rem 0.4375rem;
    border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--accent-color) 16%, transparent);
    color: var(--accent-color);
    font-weight: 700;
    font-size: .62rem;
    letter-spacing: .04em;
    white-space: nowrap;
}
/* The summary sits above the table with its filter beside it, so the count and
   the way to act on it are one thing rather than two. */
.breed-translation-card {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    align-items: center;
    justify-content: space-between;
}
.breed-translation-card .settings-intro { margin: 0; }
.breed-translation-card .btn-premium.is-active {
    border-color: var(--accent-color);
    color: var(--accent-color);
}

/* "This one needs a person." Sits before the group tag and takes the auto
   margin when it is showing, so the pair stays against the right edge. */
.breed-status-tag {
    border-radius: var(--radius-sm);
    flex: 0 0 auto;
    margin-left: auto;
    padding: 0 0.375rem 0.0625rem 0.375rem;
    background: rgba(var(--color-important-rgb), .14);
    color: var(--color-important);
    font: 700 .68rem var(--font-display);
    letter-spacing: .04em;
    white-space: nowrap;
}
.breed-status-tag[hidden] { display: none; }
.breed-fci-note-error { color: var(--color-my-dogs); }
.breed-fci-note-warn { color: var(--color-important); }

/* The FCI card reads as a profile: portrait, official name, group and standard
   number on one line, the source link at its foot. Editing happens in a modal,
   so nothing here is a form control. */
.fci-profile {
    display: flex;
    align-items: flex-start;
    gap: 0.875rem;
    margin-top: 4px;
}
.fci-profile-photo {
    flex: 0 0 auto;
    width: 96px;
    height: 96px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: var(--bg-overlay);
    overflow: hidden;
}
.fci-profile-photo img { width: 100%; height: 100%; object-fit: cover; }
.fci-profile-photo-empty { font-size: .68rem; color: var(--text-secondary); text-align: center; padding: 0 0.375rem; }
.fci-profile-facts {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    min-width: 0;
}
/* Whose name it is, then the name. The label leads the line rather than sitting
   under the numbers, because "Podengo Português" is what the CPC calls this
   breed and the FCI would call it something else. */
.fci-profile-title {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.5rem;
    min-width: 0;
}
.fci-profile-title strong { font-size: 1rem; color: var(--text-primary); word-break: break-word; }
.fci-profile-title strong:empty::before { content: '—'; color: var(--text-secondary); }
.fci-profile-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem 0.875rem;
    font-size: .78rem;
    color: var(--text-secondary);
}
.fci-profile-meta em { font-style: normal; font-weight: 600; color: var(--text-primary); }
.fci-profile-meta em:empty::before { content: '—'; font-weight: 400; color: var(--text-secondary); }
.fci-profile-hint { font-size: .72rem; color: var(--text-secondary); }
/* Whose standard this is, and the button that reads it — one line under the
   group and the number, because the name is what says which site Fetch asks. */
.fci-profile-standard {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.625rem;
    margin-top: 2px;
}
.fci-standard-name {
    font-size: .74rem;
    font-weight: 700;
    letter-spacing: .04em;
    color: var(--text-primary);
    background: var(--bg-overlay);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    padding: 0.1875rem 0.5625rem;
}
.fci-profile-standard .btn-premium { width: auto; font-size: .72rem; padding: 0.4375rem 0.75rem; }
/* The undo is a form, so that it is a POST with a token like every other write.
   It still has to sit in the row as if it were just the button inside it. */
.fci-unlink-form { display: inline-flex; }
.fci-unlink-form[hidden] { display: none; }
.fci-profile-footer {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.625rem;
    margin-top: 16px;
    padding-top: 0.875rem;
    border-top: 1px solid var(--border-color);
}
.fci-profile-footer small { font-size: .7rem; color: var(--text-secondary); }
.fci-profile-footer .btn-premium { margin-left: auto; width: auto; font-size: .72rem; padding: 0.5625rem 0.8125rem; }
.fci-profile-link { font-size: .78rem; color: var(--accent-primary); text-decoration: none; }
.fci-profile-link:hover { text-decoration: underline; }
/* Group and standard number are one line in the editor too. */
.fci-form-row { display: flex; gap: 0.75rem; }
.fci-form-row > label { flex: 1 1 0; min-width: 0; }
.fci-remove-image {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: .78rem;
}
.fci-remove-image input { width: auto; margin: 0; }

/* FCI lookup: the verdict line, then the ranked matches when the FCI's
   "contains" search returned more than this breed. */
.fci-lookup-status {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    margin: 12px 0;
    padding: 0.625rem 0.75rem;
    border-radius: 8px;
    background: var(--bg-overlay);
    font-size: .78rem;
    color: var(--text-secondary);
}
.fci-lookup-status strong { color: var(--text-primary); font-size: .8rem; }
.fci-lookup-status small { font-size: .72rem; line-height: 1.4; word-break: break-word; }
.fci-lookup-ok strong { color: var(--accent-primary); }
.fci-lookup-warn strong { color: var(--color-my-dogs); }
.fci-lookup-error strong { color: var(--color-my-dogs); }
.fci-lookup-matches {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin-bottom: 12px;
    max-height: 260px;
    overflow-y: auto;
}
.fci-match {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    width: 100%;
    padding: 0.5rem 0.625rem;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--bg-card);
    color: var(--text-primary);
    text-align: left;
    cursor: pointer;
}
.fci-match:hover { border-color: var(--accent-primary); }
.fci-match strong { font-size: .8rem; }
.fci-match small { font-size: .7rem; color: var(--text-secondary); }
.breed-name-link {
    color: inherit;
    text-decoration: none;
}
.breed-name-link:hover {
    color: var(--accent-primary);
}

@media (max-width: 768px) {
    .breed-edit-layout {
        /* minmax(0, …), not 1fr: a plain 1fr track cannot shrink below its
           content's min-content width, so anything wide inside a card — the
           alias table this once held, a long official name, an image — became
           the column's floor and pushed the whole page sideways on anything
           narrower. Wide content scrolls or wraps inside its own card instead. */
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Pull to Refresh */
.ptr-indicator {
    position: fixed;
    top: -50px;
    left: 0;
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 50px;
    z-index: var(--z-notice);
    pointer-events: none;
    transition: transform 0.2s ease;
}
.ptr-indicator .ptr-box {
    background: var(--bg-card);
    box-shadow: var(--shadow-premium);
    border-radius: 50%;
    width: 40px;
    height: 40px;
    display: flex;
    justify-content: center;
    align-items: center;
    color: var(--text-primary);
    font-size: 1.2rem;
    transition: transform 0.2s ease;
    border: 1px solid var(--border-color);
}
.ptr-indicator.ptr-ready .ptr-box {
    transform: rotate(180deg);
}
.ptr-indicator.ptr-loading .ptr-box {
    animation: ptr-spin 1s linear infinite;
    transform: rotate(0deg);
}
@keyframes ptr-spin {
    100% { transform: rotate(360deg); }
}


/* --- Users Bulk Actions & FAB --- */
.checkbox-col {
    width: 25px;
    text-align: center;
}

.users-table tbody tr.row-selected {
    background-color: rgba(var(--accent-primary-rgb), 0.1);
}

.bulk-fab-container {
    position: fixed;
    bottom: 100px;
    right: 24px;
    z-index: var(--z-modal);
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.5rem;
    opacity: 0;
    pointer-events: none;
    transform: translateY(20px) scale(0.9);
    transition: opacity 0.3s ease, transform 0.3s ease;
}

.bulk-fab-container.visible {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0) scale(1);
}

.bulk-fab-trigger {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background-color: var(--accent-primary);
    color: #fff;
    border: none;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: transform 0.2s, background-color 0.2s;
}

.bulk-fab-trigger:hover, .bulk-fab-trigger:focus-visible {
    background-color: var(--accent-primary);
    transform: scale(1.05);
}

.bulk-fab-trigger:active {
    transform: scale(0.95);
}

.bulk-fab-menu {
    background-color: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    min-width: 150px;
}

.bulk-menu-item {
    background: none;
    border: none;
    padding: 0.75rem 1rem;
    text-align: left;
    color: var(--text-primary);
    font: inherit;
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 0.2s;
    width: 100%;
}

.bulk-menu-item:hover {
    background-color: var(--bg-surface);
}

.bulk-menu-danger {
    color: var(--color-my-dogs);
}

.bulk-menu-danger:hover {
    background-color: rgba(var(--color-my-dogs-rgb), 0.1);
}

/* --- User Card Modal --- */
.user-card-trigger {
    background: none;
    border: none;
    padding: 0;
    color: var(--text-primary);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    text-decoration: underline;
    text-decoration-color: transparent;
    transition: text-decoration-color 0.2s;
}

.user-card-trigger:hover {
    text-decoration-color: var(--accent-primary);
}

.user-card-container {
    max-width: 400px;
}

.user-card-header {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: 24px;
}

.user-card-avatar {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    background-color: var(--bg-base);
    border: 1px solid var(--border-color);
}

.user-card-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.avatar-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
    font-weight: bold;
    color: var(--text-secondary);
}

.user-card-info {
    flex-grow: 1;
}

.user-card-name {
    margin: 0 0 4px 0;
    font-size: 1.125rem;
    color: var(--text-primary);
}

.user-card-email {
    font-size: 0.875rem;
    color: var(--text-secondary);
}

.user-card-details {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.user-card-detail-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.75rem;
    background-color: var(--bg-base);
    border-radius: 8px;
    border: 1px solid var(--border-color);
}

.detail-label {
    font-size: 0.875rem;
    color: var(--text-secondary);
}

.detail-value {
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--text-primary);
}

.user-badge {
    padding: 0.25rem 0.5rem;
    border-radius: 12px;
    font-size: 0.75rem;
    font-weight: 600;
}

.user-badge.verified {
    background-color: rgba(var(--color-friends-rgb), 0.1);
    color: var(--color-friends);
}

.user-badge.pending {
    background-color: rgba(var(--color-important-rgb), 0.1);
    color: var(--color-important);
}

/* ==========================================================================
   Version history (/versionlog/)
   Rendered from settings/changelog.php. The page used to carry these rules as
   inline styles emitted by a markdown pass in PHP.
   ========================================================================== */
.changelog { margin-top: 20px; }

.changelog-title {
    font-family: var(--font-display);
    font-weight: 800;
    margin-bottom: 20px;
    padding-bottom: 0.625rem;
    border-bottom: 1px solid var(--border-color);
}

.changelog-release + .changelog-release { margin-top: 28px; }

.changelog-version {
    display: flex;
    align-items: baseline;
    gap: 0.625rem;
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--accent-primary);
    margin-bottom: 10px;
}

.changelog-version time {
    font-family: var(--font-body);
    font-size: 0.8rem;
    font-weight: 400;
    color: var(--text-secondary);
}

.changelog-changes {
    padding-left: 1.25rem;
    margin: 0;
}

.changelog-changes li {
    margin-bottom: 8px;
    color: var(--text-secondary);
    line-height: 1.5;
}

.changelog-empty { color: var(--text-secondary); }
.changelog-lede { color: var(--text-secondary); font-size: .88rem; line-height: 1.6; margin: 0 0 18px; }
.info-build { color: var(--text-primary); font: 700 .95rem var(--font-display); margin: 0 0 6px; }

/* The build log: one card per deploy. */
.build-entry + .build-entry { margin-top: 12px; }
.build-head { align-items: baseline; display: flex; flex-wrap: wrap; gap: 0.625rem; }
.build-head strong { font: 700 1rem var(--font-display); }
.build-version { background: rgba(var(--accent-primary-rgb), .12); border-radius: var(--radius-sm); color: var(--accent-primary); font: 700 .78rem var(--font-display); padding: 0.125rem 0.5rem; }
.build-head time, .build-count { color: var(--text-muted); font-size: .78rem; }
/* Check source: the icon turns while the request is out, and the verdict stays
   beside the button with its evidence folded away behind it. */
.expo-show-check.is-checking .action-icon { animation: expo-check-spin 1s linear infinite; transform-origin: 50% 50%; }
@keyframes expo-check-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    /* A turning icon is the only sign the press was heard, so it does not stop
       moving -- it pulses instead of spinning. */
    .expo-show-check.is-checking .action-icon { animation: expo-check-pulse 1.4s ease-in-out infinite; }
    @keyframes expo-check-pulse { 50% { opacity: .35; } }
}
.expo-check-result { align-items: baseline; display: inline-flex; flex-wrap: wrap; font-size: .78rem; gap: 0.5rem; }
.expo-check-result strong { font: 700 .78rem var(--font-display); }
.expo-check-result[data-check-verdict="unchanged"] strong { color: var(--color-friends); }
.expo-check-result[data-check-verdict="changed"] strong { color: var(--accent-primary); }
.expo-check-result[data-check-verdict="error"] strong { color: var(--color-my-dogs); }
.expo-check-result[data-check-verdict="idle"] strong { color: var(--text-muted); }
.expo-check-detail summary { color: var(--text-muted); cursor: pointer; }
.expo-check-detail ul { color: var(--text-muted); font-size: .74rem; line-height: 1.5; margin: 6px 0 0; padding-left: 1rem; }
.expo-check-detail li { overflow-wrap: anywhere; }
/* The check's evidence sits in the card body, below the sticky header, so the
   fold-out grows the card and pushes the day list down instead of painting over
   it. Its own strip so the boundary reads. */
.expo-check-evidence { padding: 0.625rem 0.9375rem; background: var(--bg-elevated, var(--tint-subtle)); border-bottom: 1px solid var(--border-color); }
.expo-check-evidence:empty { display: none; }
.expo-check-evidence .expo-check-detail summary { font-size: .8rem; font-weight: 600; }

.build-note { color: var(--text-secondary); font-size: .86rem; line-height: 1.55; margin: 10px 0 0; padding-left: 1.125rem; }
.build-note li + li { margin-top: 4px; }
.build-headline { color: var(--text-muted); font-size: .78rem; margin: 8px 0 0; }
.build-notes-heading { color: var(--text-muted); font: 700 .72rem var(--font-display); letter-spacing: .1em; margin: 14px 0 6px; text-transform: uppercase; }
.build-notes { color: var(--text-secondary); font-size: .84rem; line-height: 1.55; margin: 0; padding-left: 1.125rem; }
.build-notes-internal { color: var(--text-muted); }
.build-files { margin-top: 12px; }
.build-files summary { color: var(--text-secondary); cursor: pointer; font-size: .8rem; }
.build-files ul { color: var(--text-muted); font-family: var(--font-mono, monospace); font-size: .76rem; line-height: 1.5; margin: 8px 0 0; padding-left: 1.125rem; }
.settings-empty { color: var(--text-secondary); }

.changelog-foot {
    margin-top: 30px;
    padding-top: 1.25rem;
    border-top: 1px solid var(--border-color);
    text-align: center;
}

.changelog-foot .btn-premium { width: auto; padding: 0.625rem 1.5rem; }

/* Remote page probe (Settings → Debug). The body panel holds somebody else's
   markup as plain text, so it scrolls on both axes rather than reflowing. */
.probe-table { border-collapse: collapse; font-size: .82rem; margin-top: 16px; width: 100%; }
.probe-table th,
.probe-table td { border-bottom: 1px solid var(--border-color); padding: 0.4375rem 0.625rem; text-align: left; vertical-align: top; }
.probe-table th { color: var(--text-muted); font-weight: 600; white-space: nowrap; width: 34%; }
.probe-table td { color: var(--text-secondary); word-break: break-word; }
/* The reachability bench is a wide, many-column table, not the probe's two-column
   key/value list, so its header cells are not a fixed third of the width. Each
   entrance opens with a full-width title row above its metrics. */
.cpc-bench-table th { width: auto; white-space: nowrap; }
.cpc-bench-table .cpc-bench-head td { border-top: 2px solid var(--border-color); padding-top: 0.75rem; }
.cpc-bench-table .cpc-bench-head strong { color: var(--text-primary, var(--text-secondary)); }
.cpc-bench-table .cpc-bench-head small { color: var(--text-muted); font-weight: 400; }
/* Why a rung did not serve the page, under its title. It is the half of the
   answer the verdict column has no room for. */
.cpc-bench-table .cpc-bench-why { color: var(--color-my-dogs); font-size: .72rem; font-weight: 400; line-height: 1.45; margin-top: 4px; }
.probe-body {
    background: var(--bg-base);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    color: var(--text-secondary);
    font: .72rem/1.5 monospace;
    max-height: 420px;
    overflow: auto;
    padding: 0.75rem;
    white-space: pre-wrap;
    word-break: break-word;
}

/* A judge's country: the flag for recognition, the code because several flags
   are indistinguishable at this size. Printed inline after the name. */
.judge-flag {
    align-items: center;
    display: inline-flex;
    gap: 0.25rem;
    margin-left: 7px;
    vertical-align: baseline;
    white-space: nowrap;
}
.judge-flag-glyph { font-size: 1.05em; line-height: 1; }
.judge-flag-code {
    background: rgba(var(--border-color-rgb), .55);
    border-radius: 4px;
    color: var(--text-muted);
    font: 600 .68rem/1 monospace;
    letter-spacing: .04em;
    padding: 0.1875rem 0.25rem;
}
.judge-card-identity h2 .judge-flag { margin-left: 8px; }

/* The show that has just finished. Shaded rather than hidden: it is behind you,
   but for a few days it is still the one being looked up. */
.recent-show-bar { opacity: .62; }
.recent-show-bar:hover,
.recent-show-bar:focus-within { opacity: 1; }
.schedule-past-badge {
    background: var(--bg-overlay);
    border-radius: 4px;
    color: var(--text-muted);
    display: inline-block;
    font-size: .65rem;
    font-weight: 800;
    letter-spacing: .05em;
    line-height: 1;
    margin-left: 8px;
    padding: 0.125rem 0.375rem;
    text-transform: uppercase;
    vertical-align: middle;
}
/* The show that has just finished is lifted out of the folded block, so it is
   already in a place of its own. It needs no dimming to say it is over — the
   tick at its front says that. */

/* Reordering a ring (administrators on the timetable, ring assistants on their
   sheet): the whole row is the handle. Nothing
   saves on drop — the bar below and its confirmation do — so the row needs no
   extra column and the breed keeps the width. */
/* The slot a dragged breed will land in: the row itself, emptied and dashed,
   while a card with its name follows the finger (Dimas, 2026-10-27). */
tr.schedule-row-dragging td {
    background: rgba(var(--accent-primary-rgb), 0.08);
    border-top: 2px dashed var(--accent-primary);
    border-bottom: 2px dashed var(--accent-primary);
    color: transparent;
}
tr.schedule-row-dragging td > * { visibility: hidden; }
tr.schedule-row-dragging-numbers { display: none; }
.schedule-drag-ghost {
    position: fixed;
    z-index: var(--z-modal);
    display: flex;
    align-items: center;
    padding: 0 1rem;
    box-sizing: border-box;
    background: var(--bg-overlay);
    border: 1px solid var(--accent-primary);
    border-radius: 10px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
    color: var(--text-primary);
    font-weight: 600;
    pointer-events: none;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* CPC Challenge: the entrance list is dragged the same way, and says so — the
   row is the grip, so the cursor has to admit that before anyone tries. While a
   drag is running, text selection would fight the finger. */
[data-cpc-sources][data-reorderable="1"] .debug-mode-switch { cursor: grab; }
[data-cpc-sources].cpc-sources-dragging { user-select: none; }
[data-cpc-sources].cpc-sources-dragging .debug-mode-switch { cursor: grabbing; }
.debug-mode-switch.cpc-source-dragging { background: var(--bg-overlay); border-radius: 10px; opacity: .6; }

/* "Changed and not saved", perched on the bottom navigation like the offline
   banner: visible wherever the operator has scrolled to, gone when the order
   is dragged back to where it started. */
.reorder-panel {
    align-items: center;
    background: var(--bg-card);
    border-top: 1px solid var(--accent-primary);
    display: flex;
    gap: 0.75rem;
    justify-content: center;
    left: 0;
    padding: 0.625rem 0.875rem;
    position: fixed;
    right: 0;
    z-index: var(--z-notice);
}
.reorder-panel span { color: var(--text-primary); font: 600 .82rem var(--font-display); }
.reorder-panel .btn-premium { flex: 0 0 auto; width: auto; }
.reorder-question { font-weight: 700; margin-top: 12px; }

/* Deciding between names nobody could choose between automatically.
   One card per breed, one block per language, because that is the shape the
   question has: "what is this breed called in Ukrainian, given these." The two
   quiet actions are deliberately quiet — taking a name is the common answer and
   the only one that should read as a button. */
.breed-review-summary .settings-intro { margin: 0; }

.breed-review-card { margin-bottom: 16px; }

.breed-review-head {
    padding-bottom: 0.75rem;
    border-bottom: 1px solid var(--border-color);
}
.breed-review-head .settings-card-title { margin-bottom: 4px; }
/* The mapping's explanation, said once for the breed rather than repeated
   under every language it proposed. */
.breed-review-note {
    margin: 6px 0 0;
    color: var(--text-muted);
    font-size: .78rem;
    line-height: 1.45;
}

.breed-review-lang { padding: 0.75rem 0; }
.breed-review-lang + .breed-review-lang { border-top: 1px solid var(--border-color); }
.breed-review-lang-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 10px;
}
/* "None of these" is one of the answers, so it sits with the question rather
   than at the bottom of the page. */
.breed-review-dismiss { margin: 0; }

.breed-review-option {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.625rem;
    padding: 0.625rem 0.75rem;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm, 8px);
    background: rgba(var(--bg-overlay-rgb), .35);
}
.breed-review-option + .breed-review-option { margin-top: 8px; }

.breed-review-option-body { min-width: 0; }
.breed-review-name {
    display: block;
    font-family: var(--font-display, inherit);
    font-size: 1rem;
    line-height: 1.3;
}
.breed-review-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-top: 3px;
    color: var(--text-muted);
    font-size: .72rem;
}
.breed-review-source { color: var(--text-secondary); }

.breed-review-confidence {
    font-weight: 700;
    letter-spacing: .03em;
    text-transform: uppercase;
}
.breed-review-confidence-certain { color: #10B981; }
.breed-review-confidence-likely  { color: var(--accent-primary); }
.breed-review-confidence-unsure  { color: var(--text-muted); }

/* .btn-premium is width:100% for the full-width forms it was written for, so
   the buttons in a row have to opt out or each one fills its own line. */
.breed-review-option-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}
.breed-review-option-actions form,
.breed-review-dismiss { flex: 0 0 auto; }
.breed-review-option-actions .btn-premium,
.breed-review-dismiss .btn-premium {
    width: auto;
    padding: 0.5rem 0.875rem;
    font-size: .78rem;
}

/* A third weight below secondary: bordered but not filled, for the answers that
   should be available without inviting a click. */
.btn-premium-ghost {
    background: transparent;
    color: var(--text-secondary);
    border: 1px solid var(--border-color);
}
.btn-premium-ghost:hover {
    background: rgba(var(--bg-overlay-rgb), .6);
    color: var(--text-primary);
}

@media (max-width: 520px) {
    /* The name and its answers stop competing for one line. */
    .breed-review-option { flex-direction: column; align-items: stretch; }
    .breed-review-option-actions { justify-content: flex-start; }
}

/* "None of the above, and I know what it should be." Last in the block because
   it is the least common answer, and present in every block because a shortlist
   being wrong about the variety is not rare. */
.breed-review-own {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 10px 0 0;
}
.breed-review-own input[type="text"] {
    flex: 1 1 200px;
    min-width: 0;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--border-input);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    color: var(--text-primary);
    font-size: .85rem;
}
.breed-review-own input[type="text"]:focus {
    border-color: var(--accent-primary);
    outline: none;
}
.breed-review-own .btn-premium {
    width: auto;
    flex: 0 0 auto;
    padding: 0.5rem 0.875rem;
    font-size: .78rem;
}

/* --- Feedback: the public form and the operator's inbox ------------------- */

.info-card + .info-card { margin-top: 16px; }
.info-card p { color: var(--text-secondary); font-size: .88rem; line-height: 1.6; margin: 0 0 10px; }
.info-card .info-lede { color: var(--text-primary); }
.info-card .info-note { color: var(--text-muted); font-size: .8rem; }
.info-card .section-header { margin-top: 0; }
.info-roadmap { color: var(--text-secondary); font-size: .88rem; line-height: 1.6; margin: 0 0 12px; padding-left: 1.25rem; }
.info-roadmap li { margin-bottom: 6px; }

/* The welcome card, while it is standing inside the dialog. The dialog already
   provides the surface, the border and the padding, so the card drops all
   three, and its own heading gives way to the dialog's title rather than
   printing the same words twice. In the page it is an ordinary card again —
   none of this applies there, which is the point of moving the node instead of
   restyling it. */
.modal-body .shows-intro-card {
    background: none;
    border: 0;
    box-shadow: none;
    padding: 0;
    margin: 0;
}
.modal-body .shows-intro-card .section-header { display: none; }
.shows-intro-dismiss { width: 100%; margin-top: 4px; }
.feedback-field { margin-bottom: 14px; }
.feedback-card .page-action-bar { margin-top: 4px; }
.feedback-reply-to { color: var(--text-muted); font-size: .82rem; margin: 0 0 14px; }
/* The honeypot. Off the page rather than display:none, because a bot that
   checks for a hidden field skips a hidden one and fills this. */
.feedback-company { height: 0; left: -9999px; overflow: hidden; position: absolute; width: 0; }

.feedback-filters { margin-bottom: 14px; }

.feedback-entry {
    border: 1px solid var(--border-color);
    border-radius: 10px;
    margin-bottom: 12px;
    padding: 0.75rem 0.875rem;
}
/* A closed entry recedes; a new one carries the accent edge. */
.feedback-entry-new { border-left: 3px solid var(--accent-primary); }
.feedback-entry-done { opacity: .55; }
.feedback-entry-head {
    align-items: baseline;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 8px;
}
.feedback-kind-tag {
    background: rgba(var(--accent-primary-rgb), .12);
    border-radius: 6px;
    color: var(--accent-primary);
    font: 700 .68rem var(--font-display);
    letter-spacing: .04em;
    padding: 0.125rem 0.5rem;
    text-transform: uppercase;
}
.feedback-entry-meta { color: var(--text-muted); font-size: .75rem; }
.feedback-entry-message { font-size: .88rem; margin: 0 0 8px; white-space: pre-line; }
.feedback-entry-contact { color: var(--text-secondary); font-size: .78rem; margin: 0 0 8px; }

/* --- Usage: daily chart, the hours of a day, and the tables --------------------------------- */

.usage-table { border-collapse: collapse; font-size: .82rem; width: 100%; }
.usage-table th {
    color: var(--text-muted);
    font: 700 .68rem var(--font-display);
    letter-spacing: .05em;
    padding: 0.375rem 0.5rem;
    text-align: left;
    text-transform: uppercase;
}
.usage-table td { border-top: 1px solid var(--border-color); padding: 0.375rem 0.5rem; }
.usage-table a { color: var(--accent-primary); text-decoration: none; }

/* Page speed cells, coloured by Google's thresholds (SHOW-11). Translucent so
   the same three read on the light and the dark card. */
.usage-vital-good { background: rgba(34, 197, 94, .22); }
.usage-vital-ok { background: rgba(245, 158, 11, .26); }
.usage-vital-poor { background: rgba(239, 68, 68, .28); }
.usage-error-message { max-width: 22rem; overflow-wrap: anywhere; }
.usage-period-line { margin: 0 0 0.5rem; font-weight: 600; color: var(--text-primary, inherit); }


/* Visitors per day: one stacked column per day, surest at the bottom. One hue
   for people (solid when confirmed, faded when probable) and gray for traffic
   nobody vouched for, so the eye reads the orange and discounts the rest. */
/* The period buttons share one row, and the arrows under them page the chart
   by the period's own length (Dimas, 2026-10-21). */
.usage-periods { flex-direction: row; margin-bottom: 0.75rem; }
.usage-periods .list-pill { flex: 1 1 0; justify-content: center; padding: 0.6rem 0.25rem; white-space: nowrap; }
/* Settings → Profiler: both filter groups on one line, each pill as wide as
   its word; they wrap on a narrow screen (Dimas, 2026-10-27, SHOW-48). */
.profiler-filters { align-items: center; display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; margin-bottom: 0.75rem; }
.profiler-filter { align-items: center; flex-direction: row; flex-wrap: wrap; gap: 0.375rem; margin: 0; }
.profiler-filter .list-pill { flex: 0 0 auto; padding: 0.4rem 0.75rem; white-space: nowrap; }
.usage-pager { align-items: center; display: flex; gap: 0.5rem; justify-content: space-between; }
.usage-pager-range { color: var(--text-secondary); font-size: .8rem; text-align: center; }
.usage-pager-arrow {
    align-items: center;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    display: inline-flex;
    font-size: 1.25rem;
    height: 2.25rem;
    justify-content: center;
    line-height: 1;
    text-decoration: none;
    width: 2.75rem;
}
.usage-pager-arrow:hover, .usage-pager-today:hover { border-color: var(--accent-primary); }
.usage-pager-arrow.is-disabled, .usage-pager-today.is-disabled { opacity: .3; }
.usage-pager-end { display: inline-flex; gap: 0.375rem; }
.usage-pager-today {
    align-items: center;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    display: inline-flex;
    font-family: var(--font-display);
    font-size: .8rem;
    font-weight: 600;
    height: 2.25rem;
    padding: 0 0.75rem;
    text-decoration: none;
    white-space: nowrap;
}
.usage-chart { display: grid; gap: 0.5rem; grid-template-columns: auto 1fr; margin-top: 14px; }
.usage-chart-axis {
    color: var(--text-muted);
    display: flex;
    flex-direction: column;
    font-size: .68rem;
    height: 180px;
    justify-content: space-between;
    line-height: 1;
    text-align: right;
}
/* Each tick's text centred on its line: the top one half above, the zero half below. */
.usage-chart-axis span:first-child { transform: translateY(-50%); }
.usage-chart-axis span:last-child { transform: translateY(50%); }
.usage-chart-plot {
    background: linear-gradient(var(--border-color), var(--border-color)) 0 50% / 100% 1px no-repeat;
    border-bottom: 1px solid var(--border-color);
    border-top: 1px dashed var(--border-color);
    display: flex;
    gap: 0.125rem;
    height: 180px;
    min-width: 0;
}
.usage-chart-day { display: flex; flex: 1 1 0; flex-direction: column; min-width: 0; position: relative; text-decoration: none; }
.usage-chart-stack { display: flex; flex: 1; flex-direction: column; gap: 0.125rem; justify-content: flex-end; }
/* A show day: a faint band behind the column, neutral so it never reads as a series. */
/* A show is a pale blue band behind its days, its name up the left of the
   first one (Dimas, 2026-10-21; the dashed lines at its ends were dropped the
   same day -- band and name are enough). The shadow carries the band half a
   gap to each side, so consecutive show days read as one block. */
.usage-chart, .usage-chart-legend {
    --usage-show-line: #3B82F6;
    --usage-show-band: color-mix(in srgb, var(--usage-show-line) 12%, transparent);
}
.usage-chart-show .usage-chart-stack {
    background: var(--usage-show-band);
    box-shadow: 0.0625rem 0 0 var(--usage-show-band), -0.0625rem 0 0 var(--usage-show-band);
}
/* The show's name, small, written up just outside the band's first day. */
.usage-chart-show-name {
    color: var(--usage-show-line);
    font-size: .6rem;
    line-height: 1;
    max-height: calc(100% - 4px);
    overflow: hidden;
    pointer-events: none;
    position: absolute;
    right: calc(100% + 0.0625rem + 3px);
    text-overflow: ellipsis;
    top: 4px; /* clear of the plot's top line */
    transform: rotate(180deg);
    white-space: nowrap;
    writing-mode: vertical-rl;
}
.usage-chart-show-name.is-inside { left: 3px; right: auto; }
.usage-chart-show-swatch { background: color-mix(in srgb, var(--usage-show-line) 35%, transparent); }
.usage-chart-day:hover .usage-chart-stack, .usage-chart-day:focus-visible .usage-chart-stack { background: color-mix(in srgb, var(--text-muted) 12%, transparent); }
.usage-chart-day.active .usage-chart-date { color: var(--text-primary); font-weight: 700; }
/* A stretch of days is picked by dragging across the plot (DIM-832). */
[data-range-select] { touch-action: pan-y; user-select: none; -webkit-user-select: none; }
.usage-chart-day.in-range .usage-chart-stack, .usage-chart-day.is-selecting .usage-chart-stack { background: color-mix(in srgb, var(--accent-primary) 14%, transparent); }
[data-range-select].is-dragging .usage-chart-day:not(.is-selecting) .usage-chart-stack { background: none; }
[data-range-select].is-dragging .usage-chart-tip { display: none; }
.usage-chart-seg { display: block; min-height: 2px; }
.usage-chart-stack > .usage-chart-seg:first-child,
.usage-chart-value + .usage-chart-seg { border-radius: 4px 4px 0 0; }
.usage-chart-confirmed { background: var(--accent-primary); }
.usage-chart-probable { background: color-mix(in srgb, var(--accent-primary) 45%, var(--bg-card)); }
.usage-chart-unverified { background: color-mix(in srgb, var(--text-muted) 40%, var(--bg-card)); }
/* New accounts: a narrow bar over the column's foot, in a colour of its own
   (Dimas, 2026-10-21). They are people already in the stack, so it overlays
   rather than adds. */
.usage-chart, .usage-chart-legend, .usage-table { --usage-new-accounts: #22C55E; --usage-total-accounts: #A78BFA; }
.usage-new-dot { display: inline-block; width: 0.5rem; height: 0.5rem; margin-left: 0.25rem; border-radius: 50%; background: var(--usage-new-accounts); vertical-align: middle; }
.usage-chart-new { background: var(--usage-new-accounts); }
.usage-chart-stack > .usage-chart-new {
    border-radius: 2px 2px 0 0;
    bottom: 0;
    left: 30%;
    min-height: 3px;
    pointer-events: none;
    position: absolute;
    width: 40%;
}
.usage-chart-stack { position: relative; }
/* The total of registered accounts (Dimas, 2026-10-23): a line with a dot a
   day over the plot, read on a scale of its own at the right. Under the
   tooltips (z-index 5), and never in the way of the pointer. */
.usage-chart.usage-chart-has-total { grid-template-columns: auto 1fr auto; }
.usage-chart-axis-right { color: var(--usage-total-accounts); text-align: left; }
.usage-chart-plot { position: relative; }
svg.usage-chart-total { height: 100%; inset: 0; overflow: visible; pointer-events: none; position: absolute; width: 100%; z-index: 1; }
.usage-chart-total-line { stroke: var(--usage-total-accounts); stroke-linejoin: round; stroke-width: 2; }
.usage-chart-total-dots { stroke: var(--usage-total-accounts); stroke-width: 7; }
.usage-chart-total-dense .usage-chart-total-dots { stroke-width: 4; }
i.usage-chart-total-accounts { background: var(--usage-total-accounts); border-radius: 50%; }
.usage-chart-line-swatch { background: linear-gradient(var(--usage-total-accounts), var(--usage-total-accounts)) 0 50% / 100% 2px no-repeat; position: relative; width: 16px; }
.usage-chart-line-swatch::after { background: var(--usage-total-accounts); border-radius: 50%; content: ''; height: 6px; left: 5px; position: absolute; top: 2px; width: 6px; }

/* The total of registered accounts (Dimas, 2026-10-23): a line with a dot a
   day over the plot, read on a scale of its own at the right. Under the
   tooltips (z-index 5), and never in the way of the pointer. */
.usage-chart.usage-chart-has-total { grid-template-columns: auto 1fr auto; }
.usage-chart-axis-right { color: var(--usage-total-accounts); text-align: left; }
.usage-chart-plot { position: relative; }
svg.usage-chart-total { height: 100%; inset: 0; overflow: visible; pointer-events: none; position: absolute; width: 100%; z-index: 1; }
.usage-chart-total-line { stroke: var(--usage-total-accounts); stroke-linejoin: round; stroke-width: 2; }
.usage-chart-total-dots { stroke: var(--usage-total-accounts); stroke-width: 7; }
.usage-chart-total-dense .usage-chart-total-dots { stroke-width: 4; }
i.usage-chart-total-accounts { background: var(--usage-total-accounts); border-radius: 50%; }
.usage-chart-line-swatch { background: linear-gradient(var(--usage-total-accounts), var(--usage-total-accounts)) 0 50% / 100% 2px no-repeat; position: relative; width: 16px; }
.usage-chart-line-swatch::after { background: var(--usage-total-accounts); border-radius: 50%; content: ''; height: 6px; left: 5px; position: absolute; top: 2px; width: 6px; }

/* The column's tooltip: its date, its shows, then its numbers, over the
   chart. Columns near either edge open it inwards. */
.usage-chart-tip {
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    bottom: calc(100% + 8px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
    display: none;

    flex-direction: column;
    gap: 0.25rem;
    left: 50%;
    min-width: 12rem;
    padding: 0.625rem 0.75rem;
    pointer-events: none;
    position: absolute;
    transform: translateX(-50%);
    z-index: 5;
}
.usage-chart-tip.is-start { left: 0; transform: none; }
.usage-chart-tip.is-end { left: auto; right: 0; transform: none; }
.usage-chart-day:hover .usage-chart-tip, .usage-chart-day:focus-visible .usage-chart-tip { display: flex; }
.usage-chart-tip-date { color: var(--text-primary); font-size: .78rem; font-weight: 700; margin-bottom: 0.125rem; white-space: nowrap; }
.usage-chart-tip-show { color: var(--usage-show-line); font-size: .72rem; white-space: nowrap; }
.usage-chart-tip-row { align-items: center; color: var(--text-secondary); display: grid; font-size: .74rem; gap: 0.5rem; grid-template-columns: 10px 1fr auto; white-space: nowrap; }
.usage-chart-tip-row b { color: var(--text-primary); font-variant-numeric: tabular-nums; font-weight: 600; }
.usage-chart-tip-row.is-plain { color: var(--text-muted); }
.usage-chart-tip-row:not(.is-plain) + .usage-chart-tip-row.is-plain { border-top: 1px solid var(--border-color); margin-top: 0.125rem; padding-top: 0.375rem; }
.usage-chart-value { color: var(--text-secondary); font-size: .66rem; text-align: center; }
.usage-chart-dense .usage-chart-value { display: none; }
/* A month of numbers does not fit across a phone; the bars still do. */
@media (max-width: 600px) { .usage-chart-mid .usage-chart-value { display: none; } }
/* The dates sit under the baseline, out of the plot's height. */
.usage-chart-date {
    color: var(--text-muted);
    font-size: .64rem;
    left: 50%;
    position: absolute;
    top: calc(100% + 4px);
    transform: translateX(-50%);
    white-space: nowrap;
}
.usage-chart-legend { color: var(--text-secondary); display: flex; flex-wrap: wrap; font-size: .74rem; gap: 0.375rem 1rem; margin: 28px 0 10px; }
.usage-chart-legend span { align-items: center; display: inline-flex; gap: 0.375rem; }
.usage-chart-swatch { border-radius: 2px; display: inline-block; height: 10px; width: 10px; }
.usage-chart-hours { margin-bottom: 26px; }
.usage-chart-hours .usage-chart-axis, .usage-chart-hours .usage-chart-plot { height: 90px; }

/* --- Who was here, on a day of the usage page ------------------------------- */

.usage-subheading { color: var(--text-primary); font: 700 .82rem var(--font-display); letter-spacing: .04em; margin: 22px 0 10px; text-transform: uppercase; }
/* The address under the name: the display name is what an operator recognises,
   the address is what tells two Marias apart. */
.usage-person-email { color: var(--text-muted); display: block; font-size: .72rem; font-weight: 400; }
.usage-person-window { color: var(--text-muted); white-space: nowrap; }
/* The tail is a summary, not a person, and reads as one. */
.usage-person-rest td { color: var(--text-muted); font-style: italic; }

/* --- Corrections journal --------------------------------------------------- */

/* Wide table, narrow phone: the table scrolls inside its card, the page never. */
.usage-table-scroll { overflow-x: auto; }
/* By type, then by source: two tables, kept apart. */
.usage-sources-kinds { margin-bottom: 1.5rem; }
.correction-action { font-weight: 600; }
.corrections-filters { margin-bottom: 14px; }

/* --- Offline banner -------------------------------------------------------- */

/* Sits on the bottom navigation's shoulder, not over the header: the header
   carries the brand, the clock and the account, and a banner across it hid all
   three. app.js sets the exact bottom offset from the navigation's own height,
   so the two never overlap whatever the safe-area inset adds. */
.offline-banner {
    background: var(--color-important, #F59E0B);
    bottom: 0;
    color: #1a1a1a;
    font: 700 .78rem var(--font-display);
    left: 0;
    letter-spacing: .03em;
    padding: 0.4375rem 0.875rem;
    position: fixed;
    right: 0;
    text-align: center;
    z-index: var(--z-notice);
}

/* --- Country visibility table --------------------------------------------- */

.countries-table-wrap {
    overflow-x: auto;
    margin-top: 1rem;
    margin-bottom: 1.5rem;
}
.countries-table {
    width: 100%;
    border-collapse: collapse;
}
.countries-table th,
.countries-table td {
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--border-color, rgba(255, 255, 255, 0.1));
    text-align: left;
}
.countries-table th {
    font-weight: 600;
    color: var(--text-secondary);
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.countries-table .cell-center {
    text-align: center;
}
.countries-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: 1rem;
}

/* --- Expositions country filter and card header --------------------------- */

.country-filter-form {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin-left: 0.75rem;
}
.country-filter-label {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: 600;
    color: var(--text-secondary);
    font-size: 0.9rem;
}
.country-select {
    background: var(--bg-card, rgba(255, 255, 255, 0.05));
    border: 1px solid var(--border-color, rgba(255, 255, 255, 0.15));
    border-radius: 6px;
    color: var(--text-primary);
    padding: 0.35rem 0.75rem;
    font-size: 0.9rem;
    cursor: pointer;
}
.country-single-name {
    font-weight: 700;
    font-size: 1.1rem;
    color: var(--text-primary);
}
.season-source-title {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}
.season-source-external-link {
    display: inline-flex;
    align-items: center;
    color: var(--text-secondary);
    transition: color 0.15s ease;
}
.season-source-external-link:hover {
    color: var(--accent-primary);
}
.season-source-external-link svg {
    width: 1.1rem;
    height: 1.1rem;
}

/* Dashboard ring cards while the quick search is on: a match in a folded part
   of the card has to show, so the folds open (over their inline display:none)
   and the fold toggles step aside. */
.schedule-ring-table.is-searching tr[data-search]:not(.is-filtered-out) { display: table-row !important; }
.schedule-ring-table.is-searching .ring-toggle-row { display: none; }
/* "My dogs only": a row that is not a breed (the "ring complete" line) has
   nothing of yours in it either. */
.schedule-ring-table.is-mine-only tbody tr:not([data-search]) { display: none; }
/* The line above a day's rings, the same on the dashboard and on a show's
   timetable (DIM-779): "Rings ›" at the left, the My dogs switch at the right. */
.breed-filter-bar { align-items: center; display: flex; flex-wrap: wrap; gap: 0.5rem 0.75rem; justify-content: flex-end; margin-bottom: 0.75rem; }
.ring-filter-head { align-items: stretch; display: inline-flex; gap: 0.375rem; margin-right: auto; }
.ring-filter-toggle { align-items: center; background: var(--bg-surface); border: 1px solid var(--border-color); border-radius: 8px; color: var(--text-secondary); cursor: pointer; display: inline-flex; font: 700 .78rem var(--font-display); gap: 0.375rem; padding: 0.375rem 0.625rem; transition: var(--transition-premium); }
.ring-filter-reset { align-items: center; background: var(--bg-surface); border: 1px solid var(--border-color); border-radius: 8px; color: var(--text-secondary); cursor: pointer; display: inline-flex; justify-content: center; padding: 0 0.5rem; transition: var(--transition-premium); }
.ring-filter-reset:hover { border-color: var(--accent-primary); color: var(--text-primary); }
.ring-filter-reset-icon { height: 0.9rem; width: 0.9rem; }
.ring-filter-toggle:hover { border-color: var(--accent-primary); color: var(--text-primary); }
.ring-filter-toggle-icon { height: 0.9rem; transition: transform .2s ease; width: 0.9rem; }
.ring-filter-toggle[aria-expanded="true"] .ring-filter-toggle-icon { transform: rotate(90deg); }
.ring-filter-current { color: var(--accent-primary); }
.schedule-ring-filter[hidden] { display: none; }
.breed-filter-bar .tracker-filters { margin-bottom: 0; }
.mine-switch { background: var(--bg-surface); border: 1px solid var(--border-color); border-radius: 8px; display: inline-flex; gap: 0.125rem; padding: 0.2rem; }
.mine-switch-option { align-items: center; background: none; border: 1px solid transparent; border-radius: 6px; color: var(--text-muted); cursor: pointer; display: inline-flex; font: 700 .78rem var(--font-display); gap: 0.1rem; padding: 0.05rem 0.3rem 0.1rem 0.2rem; transition: var(--transition-premium); }
.mine-switch-option:hover { color: var(--text-primary); }
.mine-switch-option.active { background: rgba(var(--accent-primary-rgb), .14); border-color: var(--accent-primary); color: var(--text-primary); }
.mine-switch-option:not(.active) .favorite-star { color: var(--border-color); }
/* Three answers do not fit one line on a phone; they wrap rather than scroll. */
.mine-switch { flex-wrap: wrap; justify-content: flex-end; }
/* "My timetable": one list across the rings, start–end, ring, breed, dogs —
   the sheet people copy out by hand. The window needs a wider time column. */
.schedule-own-view { margin-bottom: 1.625rem; }
/* "All rings": My timetable's heading, drawn and stuck like a ring's, so the
   one search magnifier lives on it while the list is shown (DIM-777). */
.schedule-own-head { align-items: center; color: var(--text-primary); display: flex; font: 800 1.05rem var(--font-display); margin: 0; }
.rings-sticky ~ .schedule-own-view > .schedule-own-head { background: var(--bg-base); padding: 0.375rem 6.5rem 0.625rem 0; position: sticky; top: calc(var(--header-height) + var(--rings-sticky-height, 0px)); z-index: calc(var(--z-content) - 1); }
.schedule-own-table th:first-child, .schedule-own-table td:first-child { width: 112px; white-space: nowrap; }
/* Left-aligned, so "A:15" and "8" start at one edge (Dimas, 2026-10-21, DIM-811). */
.schedule-own-table th:nth-child(2), .schedule-own-table td:nth-child(2) { width: 56px; text-align: left; }
.schedule-own-table td.own-ring { color: var(--text-primary); font-weight: 800; }
.schedule-own-table .own-time-end { color: var(--text-muted); }

/* Sign in with Google, under the email form. White with the four-colour mark,
   as Google's own guidelines ask, in both themes. */
.auth-divider { align-items: center; color: var(--text-muted); display: flex; font-size: .8rem; gap: .75rem; margin: 1.125rem 0 0.875rem; }
.auth-divider::before, .auth-divider::after { border-top: 1px solid var(--border-color); content: ""; flex: 1; }
.auth-google { display: grid; gap: 0.5rem; }
.btn-google { align-items: center; background: #fff; border: 1px solid #dadce0; border-radius: var(--radius-sm); color: #1f1f1f; cursor: pointer; display: flex; font: 600 .95rem var(--font-body); gap: .75rem; justify-content: center; min-height: 44px; padding: .625rem 1rem; width: 100%; }
.btn-google:hover { background: #f8f9fa; border-color: #c6c9ce; }
.btn-google:focus-visible { outline: 2px solid var(--accent-primary); outline-offset: 2px; }
.btn-google-mark { height: 18px; width: 18px; flex-shrink: 0; }
.auth-google-note { color: var(--text-muted); display: block; font-size: .75rem; line-height: 1.4; }
/* Sign-in (DIM-795): the providers side by side, the reset link beside "Password". */
.auth-providers { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
.auth-providers .btn-google { gap: .5rem; padding: .625rem .75rem; }
.auth-card > .auth-google-note { margin-top: .625rem; }
.auth-label-row { align-items: baseline; display: flex; gap: .75rem; justify-content: space-between; }
.auth-forgot { color: var(--accent-primary); font-size: .8rem; font-weight: 600; text-decoration: none; }
.auth-forgot:hover { text-decoration: underline; }
.profile-no-password { color: var(--text-muted); display: block; font-size: .8rem; margin-top: 0.25rem; }
.auth-google-note a { color: var(--accent-primary); }
.btn-link { background: none; border: 0; color: var(--text-secondary); cursor: pointer; font: inherit; padding: 0; text-decoration: underline; }
.btn-link:hover { color: var(--accent-primary); }
.profile-google-link { margin-top: -0.25rem; }
.profile-google-status { align-items: baseline; display: flex; flex-wrap: wrap; font-size: .85rem; gap: 0.25rem 0.75rem; margin-top: -0.25rem; }
.profile-google-status > span { color: var(--color-friends); }
.profile-google-status small { color: var(--text-muted); flex-basis: 100%; }
.profile-email-readonly { color: var(--text-secondary); cursor: default; }

/* Ring assistant mode (DIM-638) --------------------------------------------- */
.user-role-assistant { background: rgba(var(--accent-primary-rgb),.12); color: var(--accent-primary); margin-top: 0.25rem; text-transform: none; }
.assistant-permanent { align-items: flex-start; display: flex; gap: 0.5rem; }
/* .settings-form input is display:block;width:100%, which stretched the
   checkbox across half the row and pushed its label to the far side. */
.settings-form .assistant-permanent input { flex: 0 0 auto; margin: 0.25rem 0 0; width: auto; }
.settings-form .assistant-permanent span { flex: 1 1 auto; }
/* "Permanently" leaves the show choice nothing to decide; it has to look it. */
.settings-form select:disabled { cursor: not-allowed; opacity: .45; }
.assistant-permanent small { color: var(--text-muted); display: block; font-weight: 400; }
.settings-assistant { background: var(--bg-surface); border: 1px solid var(--border-color); border-radius: var(--radius-md); margin-bottom: 0.5rem; padding: 0.75rem 1rem; }
.settings-assistant .import-tabs { margin-bottom: 0; }
.settings-assistant-show { color: var(--text-secondary); font-size: .85rem; margin: 0.75rem 0 0.5rem; }
.settings-assistant-note { color: var(--text-muted); font-size: .85rem; margin-top: 0.5rem; }
/* User, Steward, Steward Pro: the name, and under it one line of what it does. */
.settings-assistant-modes .import-tab { align-items: center; display: flex; flex-direction: column; gap: 0.125rem; line-height: 1.2; padding-bottom: 0.5rem; padding-top: 0.5rem; }
.settings-assistant-mode-hint { color: var(--text-muted); font-size: .7rem; font-weight: 500; white-space: normal; }
.assistant-all-shows { margin: 0 0 0.75rem; text-align: right; }
.assistant-all-shows a { color: var(--accent-primary); font-weight: 600; text-decoration: none; }
.assistant-sheet { margin-top: 1rem; }
.assistant-sheet-summary { color: var(--text-muted); font-size: .8rem; margin: -0.25rem 0 0.5rem; }
.assistant-sheet-summary strong { color: var(--text-primary); }
.assistant-sheet-practice { margin: 0 0 0.75rem; padding: 0.625rem 0.75rem; border: 1px solid rgba(var(--color-important-rgb), 0.4); border-radius: 0.625rem; background: rgba(var(--color-important-rgb), 0.12); color: var(--text-primary); font-size: .85rem; line-height: 1.4; }
/* With the button column the heading "Dogs" spans it too, so a fixed layout
   cannot read the column widths off the heading row: the colgroup carries them. */
.assistant-table.has-start col.assistant-col-time { width: 5.25rem; }
.assistant-table.has-start col.assistant-col-dogs { width: 3.25rem; }
.assistant-table.has-start col.assistant-col-action { width: 5.25rem; }
.assistant-table.has-start th:last-child { width: auto; white-space: nowrap; }
.assistant-table td { padding-bottom: 0.375rem; padding-top: 0.375rem; }
.assistant-start-cell { text-align: right; }
.assistant-start { font-size: .8rem; min-height: 0; padding: 0.375rem 0.75rem; width: auto; }
.assistant-start.assistant-started { white-space: normal; line-height: 1.2; max-width: 9rem; }
.ring-toggle-btn { background: transparent; border: none; box-shadow: none; color: var(--text-secondary); font-size: 0.75rem; min-height: 0; padding: 0.25rem 0.75rem; }

/* The ring sheet under each breed on the assistant's page (DIM-651): the
   catalogue's classes in judging order, each with its numbers to tick off.
   A tick is green, a no-show is struck through, an unmarked number is plain. */
.assistant-classes-row td { padding: 0 0.75rem 0.625rem; }
.assistant-classes { display: grid; gap: 0.375rem; }
.assistant-class { align-items: center; display: grid; gap: 0.5rem; grid-template-columns: minmax(6.5rem, auto) 1fr auto; }
.assistant-class-name { color: var(--text-secondary); font-size: .8rem; font-weight: 600; }
.assistant-class-count { color: var(--text-muted); font-size: .8rem; min-width: 2.5rem; padding: 0 0.75rem; text-align: center; }
.assistant-numbers { display: flex; flex-wrap: wrap; gap: 0.375rem; }
.assistant-number { background: var(--bg-input); border: 1px solid var(--border-input); border-radius: 6px; color: var(--text-primary); cursor: pointer; font: 700 .9rem var(--font-display); min-height: 2.25rem; min-width: 3.25rem; padding: 0.25rem 0.5rem; transition: var(--transition-premium); }
.assistant-number.is-done { background: rgba(var(--color-friends-rgb), .18); border-color: var(--color-friends); }
.assistant-number.is-done::after { content: " ✓"; color: var(--color-friends); }
.assistant-number.is-absent { border-color: var(--color-my-dogs); color: var(--text-muted); text-decoration: line-through; }
.assistant-number.is-absent::after { content: " ✗"; color: var(--color-my-dogs); text-decoration: none; display: inline-block; }
.assistant-number:disabled { cursor: default; opacity: .7; }

/* Class results and comparisons on the ring sheet (DIM-630). A number with a
   result shows it under the number; a comparison is a row like a class, its
   lineup drawn by the server. A number that has to come back to the ring is
   dashed; the winner is filled. */
.assistant-number.has-result { display: inline-flex; flex-direction: column; line-height: 1.1; }
.assistant-number-result { color: var(--text-secondary); font: 600 .7rem var(--font-body); }
.assistant-derived { padding-left: 0.25rem; }
.assistant-derived-award { background: none; border: 1px solid var(--border-input); border-radius: 999px; color: var(--text-secondary); cursor: pointer; font-size: .75rem; padding: 0.125rem 0.625rem; }
.assistant-derived-award.is-withheld { text-decoration: line-through; }
.assistant-comparison { align-items: center; border-left: 3px solid var(--accent-primary, var(--border-input)); display: grid; gap: 0.5rem; grid-template-columns: minmax(6.5rem, auto) 1fr; padding-left: 0.5rem; }
.assistant-comparison.is-waiting { opacity: .6; }
.assistant-comparison-note { color: var(--text-muted); font-size: .75rem; grid-column: 2; }
.assistant-candidate.is-callback { border-style: dashed; border-width: 2px; }
.assistant-candidate.is-winner { background: rgba(var(--color-friends-rgb), .25); border-color: var(--color-friends); }
.assistant-candidate.is-winner::after { content: " ★"; color: var(--color-friends); }
.assistant-withhold { background: none; border: 1px dashed var(--border-input); border-radius: 6px; color: var(--text-muted); cursor: pointer; font-size: .75rem; min-height: 2.25rem; padding: 0.25rem 0.5rem; }
.assistant-withhold.is-withheld { border-style: solid; border-color: var(--color-my-dogs); color: var(--text-primary); }
.assistant-final { border-top: 1px solid var(--border-input); display: grid; gap: 0.375rem; margin-top: 0.25rem; padding-top: 0.375rem; }
.assistant-final-title { color: var(--text-secondary); font-size: .8rem; font-weight: 700; }
.assistant-result-dialog { max-width: 26rem; }
.assistant-result-label { color: var(--text-secondary); font-size: .8rem; font-weight: 600; margin: 0.5rem 0 0.375rem; }
.assistant-result-choices { display: grid; gap: 0.375rem; grid-template-columns: repeat(5, 1fr); }
.assistant-result-choices[data-result-row="qualification"] { grid-template-columns: repeat(6, 1fr); }
.assistant-result-choice { background: var(--bg-input); border: 1px solid var(--border-input); border-radius: 6px; color: var(--text-primary); cursor: pointer; font: 700 .9rem var(--font-display); min-height: 2.75rem; min-width: 0; padding: 0 0.125rem; }
.assistant-result-choice:disabled { cursor: not-allowed; opacity: .3; }
.assistant-result-choice.is-selected { background: rgba(var(--color-friends-rgb), .25); border-color: var(--color-friends); }
.assistant-result-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: space-between; margin-top: 1rem; }
/* Save and Close side by side above Absent: a light green and a light red (DIM-791). */
.assistant-result-confirm { display: grid; gap: 0.5rem; grid-template-columns: 1fr 1fr; margin-top: 1rem; }
.assistant-result-confirm .btn-premium { width: 100%; }
.assistant-result-confirm .assistant-result-save { background: rgba(var(--color-friends-rgb), .16); border-color: rgba(var(--color-friends-rgb), .45); color: var(--text-primary); }
.assistant-result-confirm .assistant-result-save:disabled { cursor: not-allowed; opacity: .4; }
.assistant-result-confirm .assistant-result-cancel { background: rgba(239, 68, 68, .14); border-color: rgba(239, 68, 68, .4); color: var(--text-primary); }

/* Start and the arrow that opens a breed's numbers sit side by side. The
   arrow points right while the numbers are folded and down while they show. */
.assistant-actions { align-items: center; display: inline-flex; gap: 0.375rem; justify-content: flex-end; }
/* Order: Start gives way to a grab handle while the running order is edited
   (Dimas, 2026-10-26). The button in the heading reads Order, then Save. */
.order-toggle {
    align-items: center;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    color: var(--text-secondary);
    cursor: pointer;
    display: inline-flex;
    font: 700 .78rem var(--font-display);
    gap: 0.375rem;
    padding: 0.375rem 0.75rem;
}
.order-actions { align-items: center; display: inline-flex; gap: 0.375rem; margin-left: auto; }
.order-reset {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    color: var(--text-secondary);
    cursor: pointer;
    display: none;
    font: 700 .78rem var(--font-display);
    padding: 0.375rem 0.75rem;
}
.is-ordering .order-reset { display: inline-flex; }
.order-reset { align-items: center; gap: 0.375rem; }
.order-cancel {
    align-items: center;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    color: var(--text-secondary);
    cursor: pointer;
    display: none;
    font: 700 .78rem var(--font-display);
    gap: 0.375rem;
    padding: 0.375rem 0.75rem;
}
.is-ordering .order-cancel { display: inline-flex; }
.order-cancel .action-icon { height: 1rem; width: 1rem; }
.order-reset .action-icon { height: 1rem; width: 1rem; }
.order-toggle .order-icon-save, .order-toggle.is-saving .order-icon-edit { display: none; }
.order-toggle.is-saving .order-icon-save { display: inline-block; }
.order-toggle.is-saving { background: rgba(var(--accent-primary-rgb), .14); border-color: var(--accent-primary); color: var(--text-primary); }
.order-toggle .action-icon { height: 1rem; width: 1rem; }
.order-toggle:disabled { opacity: .5; }
.time-ahead.is-new-time { color: var(--color-friends); text-transform: uppercase; }
.match-newtime { color: var(--color-friends); display: block; font: 700 .64rem/1.3 var(--font-display); text-transform: uppercase; }
.match-item.is-shrunk .match-newtime { display: none; }
.order-moved { display: none; }
/* The saved order's arrow, for everybody (Dimas, 2026-10-27); while ordering,
   the steward's live arrow takes its place. */
.moved-arrow { color: var(--color-friends); display: inline-flex; margin-right: 0.25rem; vertical-align: -0.125rem; }
.moved-arrow .action-icon { height: 0.875rem; width: 0.875rem; }
.is-ordering .moved-arrow { display: none; }
.is-ordering tr.is-moved .order-moved { color: var(--color-friends); display: inline-flex; margin-right: 0.25rem; vertical-align: -0.125rem; }
.order-moved .action-icon { display: none; height: 0.875rem; width: 0.875rem; }
tr.is-moved-down .order-moved .order-moved-down, tr.is-moved-up .order-moved .order-moved-up { display: inline-block; }
.order-newtime { color: var(--color-friends); display: block; font: 700 .64rem/1.3 var(--font-display); text-transform: uppercase; }
.order-handle { display: none; }
.is-ordering .order-handle {
    align-items: center;
    border: 1px solid var(--border-input);
    border-radius: 6px;
    color: var(--text-secondary);
    cursor: grab;
    display: inline-flex;
    justify-content: center;
    min-height: 2rem;
    min-width: 2rem;
    touch-action: none;
    user-select: none;
}
.order-handle .action-icon { height: 1.125rem; width: 1.125rem; pointer-events: none; }
.is-ordering .assistant-start { display: none; }
/* While ordering every breed is shown as it is, the ones already over too:
   greyed rows read as locked (Dimas, 2026-10-27). */
.is-ordering .schedule-table tr.past td { opacity: 1; }
/* Ordering moves breeds, it does not read their numbers: the catalogue arrow
   is not shown while Order is on (Dimas, 2026-10-27). */
.is-ordering .assistant-sheet-toggle { display: none; }

.assistant-sheet-toggle { align-items: center; background: none; border: 1px solid var(--border-input); border-radius: 6px; color: var(--text-secondary); cursor: pointer; display: inline-flex; justify-content: center; min-height: 2rem; min-width: 2rem; padding: 0; }
.assistant-sheet-toggle .assistant-sheet-chevron { height: 1.125rem; transition: transform .2s ease; width: 1.125rem; }
.assistant-sheet-toggle[aria-expanded="false"] .assistant-sheet-chevron { transform: rotate(-90deg); }
.assistant-classes-row.is-collapsed { display: none !important; }
/* With the arrow beside Start the last column is as wide as its two buttons,
   in whatever language Start is written — "Iniciar" is wider than "Старт",
   and a fixed width pushed the arrow out and the table into a sideways
   scroll. The table lays itself out from its content instead; the breed name
   takes what is left and wraps. */
.assistant-table.has-sheet { table-layout: auto; }
.assistant-table.has-sheet th:last-child, .assistant-table.has-sheet td:last-child { white-space: nowrap; width: 1%; }
.assistant-table.has-sheet .schedule-table-breed { overflow-wrap: anywhere; }
.assistant-table.has-sheet .assistant-classes-row td:last-child { white-space: normal; width: auto; }
.assistant-table .schedule-table-breed[data-action="toggle-sheet-row"] { cursor: pointer; }
/* Breed takes the width; time, dogs and the button column stay fixed (Dimas,
   2026-10-27). While ordering, the button column holds only the handle (and the
   numbers arrow), so it is no wider than that. */
.assistant-sheet.is-ordering .assistant-table.has-start:not(.has-sheet) col.assistant-col-action { width: 3rem; }
.assistant-table.has-sheet .schedule-table-breed { width: 100%; }
/* An auto-laid table reads width on a cell as a wish; min-width holds it. */
.assistant-table.has-sheet th:first-child, .assistant-table.has-sheet td.schedule-table-time { box-sizing: border-box; min-width: 5.25rem; width: 5.25rem; }
.assistant-table.has-sheet tr[data-item-id] > td:nth-child(3) { box-sizing: border-box; min-width: 3.25rem; width: 3.25rem; }

/* Hints under the show card on the dashboard (DIM-774). A class of their own,
   not card-premium: they are advice about the app, and must not read as one
   more show or ring card. Side by side where there is room, stacked on a phone;
   the button sits at the bottom right whatever the text length. */
.dashboard-banners {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: 0.625rem;
    margin: 3rem 0 1.5rem;
}
.dashboard-banner {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 0.9rem 1rem 0.9rem 1.15rem;
    border-radius: var(--radius-md);
    border: 1px solid rgba(var(--accent-primary-rgb), .28);
    background: linear-gradient(135deg, rgba(var(--accent-primary-rgb), .14) 0%, rgba(var(--accent-primary-rgb), .03) 60%), var(--bg-surface);
    overflow: hidden;
}
.dashboard-banner::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 0.25rem;
    background: var(--accent-primary);
}
.dashboard-banner-title {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    color: var(--text-primary);
    font-size: 0.95rem;
    line-height: 1.3;
    margin: 0 0 0.6rem;
}
.dashboard-banner-title .favorite-star,
.dashboard-banner-icon { color: var(--accent-primary); }
.dashboard-banner-icon { width: 1.125rem; height: 1.125rem; flex-shrink: 0; }
.dashboard-banner p {
    color: var(--text-secondary);
    font-size: .85rem;
    line-height: 1.5;
    margin: 0 0 0.75rem;
    flex: 1;
}
.dashboard-banner-btn { align-self: flex-end; width: auto; padding: 0.55rem 1rem; }

/* A clock adjustment is a compact practice control, not another dashboard card.
   Solid buttons that say which way they move the clock, and no wider than
   800 px (Dimas, 2026-10-27, SHOW-38): grey ones were not seen. */
.dashboard-imitation-controls { align-items: center; background: rgba(var(--color-important-rgb), .12); border: 1px solid rgba(var(--color-important-rgb), .45); border-radius: 12px; box-sizing: border-box; color: var(--text-primary); display: flex; flex-wrap: wrap; gap: .5rem; margin: 0 auto 1rem; max-width: 800px; padding: .5rem .75rem; width: 100%; }
.dashboard-imitation-controls strong { align-items: center; color: var(--color-important); display: inline-flex; font: 700 .85rem var(--font-display); gap: .35rem; margin-right: auto; white-space: nowrap; }
.dashboard-imitation-controls strong .action-icon { height: 1.1rem; width: 1.1rem; }
.dashboard-imitation-controls form { display: contents; }
.dashboard-imitation-controls .imitation-step,
.dashboard-imitation-controls .imitation-exit { align-items: center; border-radius: 8px; cursor: pointer; display: inline-flex; font: 700 .85rem var(--font-display); gap: .3rem; line-height: 1; min-height: 2.25rem; padding: .45rem .8rem; white-space: nowrap; }
.dashboard-imitation-controls .imitation-step { background: var(--color-important); border: 1px solid var(--color-important); color: #1f1300; }
.dashboard-imitation-controls .imitation-step:hover { filter: brightness(1.08); }
.dashboard-imitation-controls .imitation-exit { background: transparent; border: 1.5px solid var(--color-important); color: var(--color-important); margin-left: .25rem; }
.dashboard-imitation-controls .imitation-exit:hover { background: rgba(var(--color-important-rgb), .18); }
.dashboard-imitation-controls .imitation-step:disabled,
.dashboard-imitation-controls .imitation-exit:disabled { cursor: progress; opacity: .6; }
.dashboard-imitation-controls .action-icon { height: 1.05rem; width: 1.05rem; }
/* Amber on white is too faint for words; the light theme darkens it. */
:root[data-theme="light"] .dashboard-imitation-controls strong,
:root[data-theme="light"] .dashboard-imitation-controls .imitation-exit { border-color: #B45309; color: #B45309; }
@media (prefers-color-scheme: light) {
    :root[data-theme="system"] .dashboard-imitation-controls strong,
    :root[data-theme="system"] .dashboard-imitation-controls .imitation-exit { border-color: #B45309; color: #B45309; }
}
@media (max-width: 480px) {
    .dashboard-imitation-controls strong { flex-basis: 100%; }
    .dashboard-imitation-controls .imitation-step,
    .dashboard-imitation-controls .imitation-exit { flex: 1 1 auto; justify-content: center; }
    .dashboard-imitation-controls .imitation-exit { margin-left: 0; }
}

/* The row standing in for a breed while the Lists page saves it (DIM-776). */
.list-item-pending .breed-item-name,
.list-item-failed .breed-item-name { font-family: var(--font-display); font-weight: 600; }
.list-item-pending .breed-item-meta,
.list-item-failed .breed-item-meta { display: flex; flex-direction: column; gap: 0.25rem; }
.list-item-status {
    align-items: center;
    color: var(--text-muted);
    display: inline-flex;
    font-size: .8rem;
    gap: 0.5rem;
}
.list-item-failed .list-item-status { color: var(--color-my-dogs); }
.list-item-spinner {
    animation: list-item-spin .8s linear infinite;
    border: 2px solid rgba(var(--accent-primary-rgb), .25);
    border-radius: 50%;
    border-top-color: var(--accent-primary);
    display: inline-block;
    height: 0.875rem;
    width: 0.875rem;
}
@keyframes list-item-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .list-item-spinner { animation-duration: 2.4s; } }

/* Create a list, and change the open one, on the line under the kinds (DIM-775).
   On a phone the two share the line rather than stacking into a wall. */
.list-type-actions { justify-content: flex-end; margin-top: 0; }
@media (max-width: 560px) {
    .list-type-actions .btn-premium,
    .list-type-actions .bulk-actions { flex: 0 1 auto; min-width: 0; }
    .list-type-actions .btn-premium { font-size: .74rem; letter-spacing: .03em; padding: 0.7rem 0.5rem; }
    .list-type-actions .bulk-actions-trigger { width: 100%; }
}
.list-items-actions { margin: 0 0 0.75rem; }

/* A show list's pin, in the list's colour, where other lists have a dot (DIM-775). */
.list-pill-pin { display: inline-flex; flex: 0 0 auto; }
.list-pill-pin-icon { height: 1rem; stroke-width: 2; width: 1rem; }


/* The open list's heading carries its Change menu at the right, after the rule
   (DIM-775). The menu is a chip, and its panel must not inherit the heading's
   capitals and letter spacing. */
.list-items-heading .bulk-actions { order: 1; }
/* Share beside Change, after the rule (DIM-792). */
.list-items-heading .list-share-chip { order: 2; }

/* The mark picker beside the colour (DIM-793): one button, and the marks to
   choose from under the row, all in the list's colour. */
.list-create-icon { display: flex; flex: 0 0 auto; flex-direction: column; }
.list-icon-button { align-items: center; background: var(--bg-input); border: 1px solid var(--border-input); border-radius: 7px; cursor: pointer; display: inline-flex; height: 42px; justify-content: center; width: 52px; }
.list-icon-button:hover { border-color: var(--accent-primary); }
.list-icon-grid { background: var(--bg-input); border: 1px solid var(--border-input); border-radius: 10px; display: grid; gap: 0.25rem; grid-template-columns: repeat(auto-fill, minmax(2.5rem, 1fr)); margin-top: 0.625rem; padding: 0.375rem; }
.list-icon-grid[hidden] { display: none; }
.list-icon-choice { align-items: center; background: none; border: 1px solid transparent; border-radius: 8px; cursor: pointer; display: inline-flex; height: 2.5rem; justify-content: center; width: 2.5rem; }
.list-icon-choice:hover { border-color: var(--border-input); }
.list-icon-choice.is-selected { background: rgba(var(--accent-primary-rgb), .14); border-color: var(--accent-primary); }
.list-icon-dot { border-radius: 50%; display: inline-block; height: 0.75rem; width: 0.75rem; }
.list-icon-pin { display: inline-flex; }
.list-icon-pin-icon { height: 1.35rem; stroke-width: 2; width: 1.35rem; }
/* On a phone the list's name needs the room: Share keeps its icon only. */
@media (max-width: 520px) { .list-share-chip .list-share-label { display: none; } }
.list-share-hint { color: var(--text-secondary); font-size: .9rem; margin: 0 0 0.75rem; }
.list-share-url { background: var(--bg-input); border: 1px solid var(--border-input); border-radius: 8px; box-sizing: border-box; color: var(--text-primary); font: 500 .85rem var(--font-body, inherit); padding: 0.625rem 0.75rem; width: 100%; }
.list-share-status { color: var(--color-friends); font-size: .85rem; margin: 0.5rem 0 0; }
.list-share-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: space-between; margin-top: 1rem; }
.list-edit-chip { cursor: pointer; color: var(--text-secondary); text-transform: none; letter-spacing: normal; }
.list-edit-chip:hover { border-color: var(--accent-primary); color: var(--text-primary); }
.list-edit-chip .action-icon { height: 0.9rem; width: 0.9rem; }
.list-items-heading .bulk-actions-menu { font-size: .9rem; letter-spacing: normal; text-transform: none; }

/* The mark in front of a breed on the Lists page: the list's own, not a control. */
.list-item-mark { cursor: default; display: inline-flex; margin-right: 0.375rem; vertical-align: middle; }
.list-item-mark.list-pill-dot { margin-right: 0.5rem; }

/* The owner's comment on a show list, under its heading (DIM-775). */
.list-comment { color: var(--text-muted); font-size: .85rem; margin: -0.5rem 0 0.75rem; }

/* Create-list dialog: the main field and its colour on one line (DIM-775). */
.list-create-row { align-items: flex-end; display: flex; gap: 0.75rem; }
.list-create-main { flex: 1 1 auto; min-width: 0; }
.list-create-colour { flex: 0 0 auto; }
/* The show list's day beside its show (DIM-797), and the two rows apart. */
.list-create-day { flex: 0 1 9.5rem; min-width: 7rem; }
@media (max-width: 520px) { .list-create-day { flex-basis: 7rem; } }
.list-create-row + .list-create-row { margin-top: 0.875rem; }
/* Save and Cancel under the breed dialog's ticks (DIM-801), as in the ring's
   result dialog: a light green and a light red. */
.breed-lists-confirm { display: grid; gap: 0.5rem; grid-template-columns: 1fr 1fr; margin-top: 1.25rem; }
.breed-lists-confirm .btn-premium { width: 100%; }
.breed-lists-confirm .breed-lists-save { background: rgba(var(--color-friends-rgb), .16); border-color: rgba(var(--color-friends-rgb), .45); color: var(--text-primary); }
.breed-lists-confirm .breed-lists-save:disabled { cursor: not-allowed; opacity: .4; }
.breed-lists-confirm .breed-lists-cancel { background: rgba(239, 68, 68, .14); border-color: rgba(239, 68, 68, .4); color: var(--text-primary); }
/* The Save dialog of a shared list (DIM-798): the section first, as two chips. */
.list-save-form > * + * { margin-top: 0.875rem; }
.list-save-sections { display: grid; gap: 0.5rem; grid-template-columns: 1fr 1fr; }
.list-save-section { align-items: center; background: var(--bg-input); border: 1px solid var(--border-input); border-radius: var(--radius-sm); cursor: pointer; display: flex; font-weight: 600; gap: 0.5rem; justify-content: center; min-height: 2.875rem; padding: 0 0.75rem; }
.list-save-section:has(input:checked) { border-color: var(--accent-primary); color: var(--text-primary); background: rgba(var(--accent-primary-rgb), .12); }
.list-save-section input { accent-color: var(--accent-primary); }
.list-create-colour input[type="color"] { background: var(--bg-input); border: 1px solid var(--border-input); border-radius: 7px; height: 42px; padding: 0.1875rem; width: 60px; }
/* One height for every field of the list dialogs (Dimas, 2026-10-20): the
   colour and the icon were 42 px beside fields of 44–46 px, and px does not
   follow the interface size. */
.list-create-row .input-field,
.list-create-row .list-create-colour input[type="color"],
.list-create-row .list-icon-button { box-sizing: border-box; height: 2.875rem; }

/* Show lists in two groups, upcoming then past (DIM-775). */
.list-group-title { color: var(--text-muted); font: 700 .75rem var(--font-display); letter-spacing: .06em; margin: 1.25rem 0 0.5rem; text-transform: uppercase; }
.list-group-title + .list-pills { margin-top: 0; }
.list-show-all { margin-bottom: 1.25rem; }

/* An open list's breed count, in a circle after its name (DIM-775). */
.list-count {
    align-items: center;
    background: rgba(var(--accent-primary-rgb), .14);
    border: 1px solid rgba(var(--accent-primary-rgb), .45);
    border-radius: 999px;
    color: var(--text-primary);
    display: inline-flex;
    font-size: .8rem;
    height: 1.6rem;
    justify-content: center;
    letter-spacing: 0;
    margin-left: 0.35rem;
    min-width: 1.6rem;
    padding: 0 0.4rem;
    vertical-align: middle;
}

/* A breed on a show list, in the timetable and on the dashboard: the list's pin
   in its colour, where other lists have their dot (DIM-775). */
.breed-list-pin { display: inline-flex; vertical-align: -0.125rem; }
.breed-list-pin-icon { height: 0.95rem; stroke-width: 2; width: 0.95rem; }

/* The venue map button on the dashboard's Rings line, after the rule at the
   right; the heading's capitals and spacing are not the button's. */
.section-header .section-header-action { font-size: .8rem; letter-spacing: normal; margin-left: 0; order: 1; text-transform: none; }

/* A show over several halls: one row of ring buttons per hall, its letter
   first, the buttons in shared columns across the rows (DIM-777). */
.schedule-ring-filter.has-halls { display: flex; flex-direction: column; gap: 0.375rem; }
.ring-hall-row { align-items: center; display: grid; gap: 0.375rem; grid-template-columns: 1.25rem 1fr; }
.ring-hall-label { color: var(--accent-primary); font: 700 .8rem var(--font-display); text-align: center; }
/* "A:" before a ring's name in a show of several halls (Dimas, 2026-10-21, DIM-811). */
.ring-hall-prefix { color: var(--accent-primary); }
/* Each hall its own colour, by its place in the layout (DIM-812). Mid tones,
   one value for both themes like the accent: each reads on white and on the
   dark ground, and they stay apart from the orange and from each other. */
.ring-hall-label.hall-2, .ring-hall-prefix.hall-2 { color: var(--hall-2); }
.ring-hall-label.hall-3, .ring-hall-prefix.hall-3 { color: var(--hall-3); }
.ring-hall-label.hall-4, .ring-hall-prefix.hall-4 { color: var(--hall-4); }
.ring-hall-buttons { display: grid; gap: 0.375rem; grid-template-columns: repeat(var(--ring-columns, 1), minmax(0, 1fr)); }

/* The Rings line and the filters under it stay on screen while the ring cards
   or the timetable scroll beneath, folded or not (Dimas, 2026-10-20). Parked
   under the fixed header, on the page's own colour so nothing shows through. */
.rings-sticky {
    background: var(--bg-base);
    padding: 0.5rem 0 0.75rem;
    position: sticky;
    top: var(--header-height);
    z-index: var(--z-content);
}
.rings-sticky-headed { margin-top: 2rem; }   /* the dashboard's, which carries the Rings heading */
.rings-sticky > .section-header { margin-top: 0; }
.rings-sticky .schedule-search { margin-bottom: 0; }

/* Each ring's heading sticks under the filter block while its ring is on
   screen, and the next ring's heading pushes it out (Dimas, 2026-10-20): a
   sticky element stays inside its own section, so the section's end is where
   it lets go. --rings-sticky-height is the block's measured height, kept by
   watchRingsSticky(), since folding the ring buttons changes it. */
.rings-sticky ~ .schedule-ring-tables .schedule-ring-table > h2 {
    background: var(--bg-base);
    margin-bottom: 0;
    padding: 0.375rem 0 0.625rem;
    position: sticky;
    top: calc(var(--header-height) + var(--rings-sticky-height, 0px));
    z-index: calc(var(--z-content) - 1);
}

/* One magnifier for the page (DIM-777). It lives in the heading of the ring at
   the top — placeRingSearch() moves it there — so it rides with that heading,
   pushed out with it, and never hangs over a table. "Ring N" has a fixed width
   reserved, so it never wraps, and the open field takes everything from there
   to the magnifier, over the judge (Dimas, 2026-10-20; was 70%, then measured).
   .ring-search-band is only its home before the script places it, and where it
   waits when no ring is shown. */
.rings-sticky ~ .schedule-ring-tables { --ring-label-w: 5.3rem; }   /* "Ringue 88", the widest label in any language (84.3px at 1.05rem) */
.rings-sticky ~ .schedule-ring-tables .schedule-ring-table > h2 { align-items: center; flex-wrap: nowrap; padding-right: 6.5rem; }
/* One line: a long judge's name ends in an ellipsis rather than wrapping under "Ring N". */
.rings-sticky ~ .schedule-ring-tables .schedule-ring-table > h2 > small { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rings-sticky ~ .schedule-ring-tables .schedule-ring-table > h2 > span:first-child { flex: 0 0 var(--ring-label-w); white-space: nowrap; }
.ring-search-band { height: 0; position: relative; }
.ring-search-band-inner { align-items: center; display: flex; gap: 0.375rem; height: 2.75rem; justify-content: flex-end; position: absolute; right: 0; top: 0; z-index: 1; }
.schedule-ring-table > h2 > .ring-search-band-inner, .schedule-own-view > h2 > .ring-search-band-inner { bottom: 0; height: auto; }
.ring-search-band-inner.is-open { left: var(--ring-search-left, calc(var(--ring-label-w, 5.3rem) + 0.5rem)); }
.ring-search-band-inner .ring-search { animation: ring-search-slide .18s ease-out; flex: 1 1 auto; margin: 0; min-width: 0; }
.ring-search-band-inner .ring-search .schedule-search-input { font-size: .8rem; padding-bottom: 0.375rem; padding-top: 0.375rem; }
.ring-search-btn { align-items: center; background: var(--bg-base); border: 1px solid transparent; border-radius: 8px; color: var(--text-secondary); cursor: pointer; display: inline-flex; flex: 0 0 auto; font: 700 .78rem var(--font-display); gap: 0.3rem; height: 2rem; justify-content: center; min-width: 2rem; padding: 0 0.5rem; transition: var(--transition-premium); }
/* The word beside the magnifier (Dimas, 2026-10-20); it steps aside while the field is out. */
.ring-search-band-inner.is-open .ring-search-word { display: none; }
.ring-search-btn:hover, .ring-search-band-inner.is-open .ring-search-btn { border-color: var(--border-color); color: var(--accent-primary); }
.ring-search-btn .action-icon { height: 1.1rem; width: 1.1rem; }
@keyframes ring-search-slide { from { clip-path: inset(0 0 0 100%); } to { clip-path: inset(0 0 0 0); } }
@media (prefers-reduced-motion: reduce) { .ring-search-band-inner .ring-search { animation: none; } }

/* The day beside "Rings" on the dashboard: the same weight, a quieter colour. */
.rings-heading-date { color: var(--text-muted); letter-spacing: 0.04em; }

/* "By group/breed": a group's name beside its number may run longer than the
   room kept for "Ring N", so it takes its own width (DIM-777). */
.rings-sticky ~ .schedule-ring-tables .schedule-group-table > h2 > .schedule-group-label { flex: 0 0 auto; }
