/* ===========================
   Atrict Design System
   Custom CSS, no framework dependency
   =========================== */

/* --- Reset --- */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

/* --- CSS Variables --- */
:root,
[data-theme="light"] {
    color-scheme: light;

    /* neutrals */
    --color-bg: #ffffff;
    --color-bg-secondary: #f7f8fa;
    --color-bg-tertiary: #eef0f3;
    --color-surface: #ffffff;
    --color-border: #e0e3e8;
    --color-border-light: #eef0f3;

    /* text */
    --color-text: #1a1d23;
    --color-text-secondary: #5f6570;
    --color-text-muted: #8b919d;
    --color-text-inverse: #ffffff;

    /* accent */
    --color-primary: #2563eb;
    --color-primary-hover: #1d4ed8;
    --color-primary-light: rgba(37, 99, 235, 0.08);
    --color-danger: #dc2626;
    --color-danger-hover: #b91c1c;
    --color-success: #16a34a;

    /* shadows */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
    --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.08);

    /* misc */
    --header-bg: rgba(255, 255, 255, 0.85);
    --header-border: var(--color-border);
}

[data-theme="dark"] {
    color-scheme: dark;

    --color-bg: #0f1117;
    --color-bg-secondary: #181a22;
    --color-bg-tertiary: #1f222c;
    --color-surface: #181a22;
    --color-border: #2a2d38;
    --color-border-light: #1f222c;

    --color-text: #e4e6eb;
    --color-text-secondary: #9da2ae;
    --color-text-muted: #6b7280;
    --color-text-inverse: #0f1117;

    --color-primary: #5b8def;
    --color-primary-hover: #7ba4f7;
    --color-primary-light: rgba(91, 141, 239, 0.14);
    --color-danger: #ef4444;
    --color-danger-hover: #f87171;
    --color-success: #22c55e;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.4);

    --header-bg: rgba(15, 17, 23, 0.85);
    --header-border: var(--color-border);
}

/* --- Typography --- */
html {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
    font-size: 16px;
    line-height: 1.6;
    color: var(--color-text);
    background-color: var(--color-bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

body {
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
}

h1, h2, h3, h4, h5, h6 {
    line-height: 1.3;
    font-weight: 600;
    color: var(--color-text);
    letter-spacing: -0.01em;
}

h1 { font-size: 1.875rem; }
h2 { font-size: 1.5rem; }
h3 { font-size: 1.25rem; }
h4 { font-size: 1.125rem; }

p { margin-bottom: 1rem; }
p:last-child { margin-bottom: 0; }

a {
    color: var(--color-primary);
    text-decoration: none;
    transition: color 0.15s;
}

a:hover {
    color: var(--color-primary-hover);
}

small {
    font-size: 0.875rem;
    color: var(--color-text-secondary);
}

strong {
    font-weight: 600;
}

time {
    font-variant-numeric: tabular-nums;
}

/* --- Layout --- */
.app-header {
    position: sticky;
    top: 0;
    z-index: 100;
    background: var(--header-bg);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--header-border);
    height: 56px;
    display: flex;
    align-items: center;
    padding: 0 1.5rem;
}

.app-header-inner {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.app-header-left {
    display: flex;
    align-items: center;
    gap: 1.5rem;
}

.app-header-logo {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: 700;
    letter-spacing: -0.04em;
    font-size: 1.0625rem;
    color: var(--color-text);
    text-decoration: none;
}

.app-header-logo:hover {
    color: var(--color-text);
}

.app-header-logo img {
    width: 22px;
    height: 22px;
    display: block;
    border-radius: 5px;
}

/* compact public language strip rendered into the header for anonymous
   pages (login/error/legal/offline). Three small toggle buttons; the active
   one is filled. Keep this tiny — it's the only control on these pages. */
.public-lang-strip {
    display: inline-flex;
    gap: 2px;
    padding: 2px;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border);
    border-radius: 8px;
}

.public-lang-btn {
    appearance: none;
    background: transparent;
    border: none;
    padding: 0.125rem 0.5rem;
    border-radius: 6px;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--color-text-muted);
    cursor: pointer;
    transition: background 0.12s, color 0.12s;
    line-height: 1.4;
}

.public-lang-btn:hover { color: var(--color-text); }

.public-lang-btn.active {
    background: var(--color-surface);
    color: var(--color-text);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}

.app-header-right {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.app-header-email {
    display: none;
    font-size: 0.8125rem;
    color: var(--color-text-muted);
}

@media (min-width: 768px) {
    .app-header-email {
        display: block;
    }
}

.app-main {
    flex: 1;
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 2rem 1.5rem 4rem;
}

/* --- Buttons --- */
button, .btn, [role="button"] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.5rem 1rem;
    border: 1px solid transparent;
    border-radius: 6px;
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 500;
    line-height: 1.4;
    cursor: pointer;
    transition: all 0.15s;
    text-decoration: none;
    white-space: nowrap;
}

.btn-primary,
button[type="submit"]:not(.btn-secondary):not(.btn-outline):not(.btn-ghost):not(.btn-danger):not(.btn-google):not(.btn-link):not(.public-lang-btn):not(.user-menu-lang-btn):not(.user-menu-item),
a[role="button"]:not(.btn-secondary):not(.btn-outline):not(.btn-danger):not(.btn-ghost):not(.btn-google):not(.btn-link) {
    background-color: var(--color-primary);
    color: var(--color-text-inverse);
    border-color: var(--color-primary);
}

.btn-primary:hover,
button[type="submit"]:not(.btn-secondary):not(.btn-outline):not(.btn-ghost):not(.btn-danger):not(.btn-google):not(.btn-link):not(.public-lang-btn):not(.user-menu-lang-btn):not(.user-menu-item):hover,
a[role="button"]:not(.btn-secondary):not(.btn-outline):not(.btn-danger):not(.btn-ghost):not(.btn-google):not(.btn-link):hover {
    background-color: var(--color-primary-hover);
    border-color: var(--color-primary-hover);
    color: var(--color-text-inverse);
}

/* class-named submit buttons that opt out of the primary style above. The
   `:not(.public-lang-btn)` etc. chain keeps the universal selector above
   from poaching them; these rules below restate the variant style with
   higher specificity so the visual result matches the variant. */
button[type="submit"].public-lang-btn {
    background: transparent;
    color: var(--color-text-muted);
    border: none;
}

button[type="submit"].public-lang-btn.active {
    background: var(--color-surface);
    color: var(--color-text);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}

.btn-secondary {
    background-color: var(--color-bg-tertiary);
    color: var(--color-text);
    border-color: var(--color-border);
}

.btn-secondary:hover {
    background-color: var(--color-border);
    color: var(--color-text);
}

.btn-outline {
    background-color: transparent;
    color: var(--color-text-secondary);
    border-color: var(--color-border);
}

.btn-outline:hover {
    background-color: var(--color-bg-tertiary);
    color: var(--color-text);
}

.btn-ghost {
    background-color: transparent;
    color: var(--color-text-secondary);
    border-color: transparent;
    padding: 0.375rem 0.625rem;
}

/* button styled as an inline text link — for "submit that looks like an anchor"
   places where we want a POST endpoint but the visual is a link (e.g. the
   "Register this device" footer next to a count). honors the link colors and
   strips button chrome. */
.btn-link {
    background-color: transparent;
    border: 0;
    padding: 0;
    margin: 0;
    color: var(--color-primary);
    cursor: pointer;
    font: inherit;
    text-decoration: underline;
    text-underline-offset: 2px;
}
.btn-link:hover { color: var(--color-primary-hover); }

.btn-ghost:hover {
    background-color: var(--color-bg-tertiary);
    color: var(--color-text);
}

/* danger button: outlined in red so it reads "destructive" at a glance and
   doesn't blur into the Save (filled blue) primary submit on the same page. */
.btn-danger {
    background-color: transparent;
    color: var(--color-danger);
    border-color: var(--color-danger);
}

.btn-danger:hover {
    background-color: var(--color-danger);
    color: var(--color-text-inverse);
    border-color: var(--color-danger);
}

.btn-sm {
    padding: 0.25rem 0.5rem;
    font-size: 0.75rem;
    border-radius: 4px;
}

.btn-google {
    width: 100%;
    background: var(--color-surface);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    font-weight: 500;
    padding: 0.6875rem 1rem;
    gap: 0.625rem;
}

.btn-google:hover {
    background: var(--color-bg-secondary);
    color: var(--color-text);
    border-color: var(--color-border);
}

.btn-google svg {
    width: 18px;
    height: 18px;
}

/* --- Forms --- */
label {
    display: block;
    margin-bottom: 1.25rem;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--color-text-secondary);
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="date"],
input[type="search"],
input[type="url"],
input[type="tel"],
textarea,
select {
    display: block;
    width: 100%;
    padding: 0.5rem 0.75rem;
    margin-top: 0.375rem;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    background-color: var(--color-bg);
    color: var(--color-text);
    font-family: inherit;
    font-size: 0.9375rem;
    line-height: 1.5;
    transition: border-color 0.15s, box-shadow 0.15s;
    outline: none;
}

input:focus, textarea:focus, select:focus {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--color-primary-light);
}

input::placeholder, textarea::placeholder {
    color: var(--color-text-muted);
}

textarea {
    resize: vertical;
    min-height: 80px;
}

/* memory text auto-grows with content (Safari ≥17.4, Chrome ≥123, FF ≥133); older
   browsers fall back to the fixed rows=3 from the markup. */
.memory-form textarea[name="text"],
.add-memory-card textarea[name="text"] {
    field-sizing: content;
    max-height: 20rem;
    resize: none;
}

input[type="file"]:not([hidden]):not(.avatar-file-input):not([data-file-picker-input]) {
    display: block;
    width: 100%;
    padding: 0.5rem 0;
    margin-top: 0.375rem;
    border: none;
    background: transparent;
    color: var(--color-text-secondary);
    font-family: inherit;
    font-size: 0.875rem;
    cursor: pointer;
}

/* --- Details/Summary --- */
details {
    margin-bottom: 1.25rem;
}

details summary {
    cursor: pointer;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--color-text-secondary);
    padding: 0.5rem 0;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

details summary::before {
    content: '\25B8';
    font-size: 0.75rem;
    transition: transform 0.15s;
}

details[open] summary::before {
    transform: rotate(90deg);
}

details summary::-webkit-details-marker {
    display: none;
}

details[open] > *:not(summary) {
    animation: detailsOpen 0.2s ease-out;
}

@keyframes detailsOpen {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: translateY(0); }
}

/* --- Card --- */
.card {
    background-color: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    padding: 1.5rem;
}

/* --- Page Header --- */
.page-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1rem;
    margin-bottom: 2rem;
}

.page-header h1 {
    margin: 0;
}

/* --- Back Link --- */
.back-link {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    font-size: 0.875rem;
    color: var(--color-text-muted);
    margin-bottom: 1rem;
}

/* arrow lives in CSS so the RTL override can flip it without view edits */
.back-link::before {
    content: '\2190';
    font-size: 1em;
    line-height: 1;
}

.back-link:hover {
    color: var(--color-text);
}

/* --- Grid --- */
.grid-2 {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
}

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

.grid-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 1.25rem;
}

/* phones: 2-col instead of single — 220px min would otherwise collapse to 1-col on a 360px viewport.
   minmax(0, 1fr) lets columns shrink below their min-content width so long words / button labels
   ("Воспоминания") can't blow the grid past the viewport on narrow screens. */
@media (max-width: 575px) {
    .grid-cards {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: 0.75rem;
    }

    .kid-card {
        padding: 1rem 0.75rem;
    }

    /* on narrow phones the action buttons (e.g. RU "Воспоминания") are
       wider than half the card; stack vertically so each gets a full row */
    .kid-card-actions {
        flex-direction: column;
        align-items: stretch;
    }

    .kid-avatar,
    .kid-avatar-placeholder {
        width: 56px;
        height: 56px;
        font-size: 1.5rem;
    }

    /* mobile: collapse metric-only entries to roughly half height. The
       timeline-meta (age + occurred-on) row is also redundant on these
       since the value is the whole point and the date/age is captured by
       the parent timeline grouping; hide it. */
    .timeline-entry.type-metric { margin-bottom: 0.875rem; }
    .timeline-entry.type-metric .memory-item {
        padding: 0.5rem 0.75rem;
    }
    .timeline-entry.type-metric .memory-content {
        line-height: 1.35;
        padding-right: 0;
    }
    .timeline-entry.type-metric .memory-content .memory-metrics {
        margin: 0;
        padding: 0;
        gap: 1rem;
        font-size: 0.875rem;
    }
    .timeline-entry.type-metric .timeline-meta { display: none; }
    .timeline-entry.type-metric .timeline-marker { margin-top: 0.125rem; }
    .timeline-entry.type-metric .timeline-marker svg {
        width: 14px;
        height: 14px;
    }

    /* growth sidebar: trim aggressively on mobile. Drop the "Growth" card
       heading, hide the weight chart and per-chart titles (the .stat block
       already shows the latest values), and shrink the height chart so it
       doesn't dominate the viewport. Chart is the last node in the card so
       margin-bottom is wasted space stacked on top of the card padding;
       also trim the card padding itself since the inner content is now
       just stat values + a 40px line. */
    .growth-stats { padding: 0.875rem 1rem; }
    .growth-stats > h3 { display: none; }
    .growth-stats .current-stats { margin-bottom: 0.5rem; }
    .chart-container--weight { display: none; }
    .chart-container h4 { display: none; }
    .chart-container { margin-bottom: 0; }
    .chart-container .chart-svg { height: 40px; }

    /* on mobile the perm-row actions don't fit on the same line as the
       avatar+text (especially with two buttons + role badge). stack the
       actions onto a second line, anchored to the inline-end edge
       (right in LTR, left in RTL via flex-end) so the row reads
       top-to-bottom: who/what, then controls. */
    .perm-row,
    [data-family-row] .perm-row-view {
        flex-direction: column;
        align-items: stretch;
        gap: 0.625rem;
    }
    .perm-row-actions {
        flex-wrap: wrap;
        justify-content: flex-end;
        align-self: flex-end;
    }
    /* edit mode: stack input above Save/Cancel on narrow screens */
    [data-family-row].is-editing .perm-row-edit { flex-wrap: wrap; }
    [data-family-row].is-editing .perm-row-edit input[name="name"] { flex: 1 1 100%; }
    [data-family-row].is-editing .perm-row-edit-actions {
        width: 100%;
        justify-content: flex-end;
    }
}

/* --- Theme Toggle --- */
.theme-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    background: transparent;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    cursor: pointer;
    color: var(--color-text-secondary);
    transition: all 0.15s;
    padding: 0;
}

.theme-toggle:hover {
    background-color: var(--color-bg-tertiary);
    color: var(--color-text);
}

.theme-toggle svg {
    width: 18px;
    height: 18px;
    display: block;
}

/* --- Kids --- */
.kid-card {
    position: relative;
    text-align: center;
    padding: 1.5rem 1rem;
    cursor: pointer;
    transition: border-color 0.12s, box-shadow 0.12s, transform 0.12s;
}

.kid-card:hover {
    border-color: var(--color-primary);
    box-shadow: 0 4px 14px rgba(37, 99, 235, 0.08);
    transform: translateY(-1px);
}

/* draw the focus ring on the card host when the stretched link is focused
   so the visible affordance matches the click target (the whole card). */
.kid-card:has(.kid-card-link:focus-visible) {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* stretched link: a transparent <a> covers the card and carries the primary
   navigation. Secondary actions inside .kid-card-actions sit above it via
   z-index so they remain clickable. */
.kid-card-link {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    z-index: 1;
    color: inherit;
    text-decoration: none;
}

.kid-card-link:focus { outline: none; }

.kid-card .kid-card-actions { position: relative; z-index: 2; }

.kid-card a {
    text-decoration: none;
    color: inherit;
}

.kid-card h3 {
    margin: 0.75rem 0 0.25rem;
    font-size: 1.125rem;
}

.kid-card small {
    display: block;
    margin-bottom: 1rem;
}

.kid-card-actions {
    display: flex;
    gap: 0.5rem;
    justify-content: center;
    margin-top: 1rem;
}

.kid-avatar {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    object-fit: cover;
    display: block;
    margin: 0 auto;
}

.kid-avatar-lg {
    width: 96px;
    height: 96px;
    border-radius: 50%;
    object-fit: cover;
    display: block;
}

.kid-avatar-placeholder {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    background-color: var(--color-primary);
    color: var(--color-text-inverse);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;
    font-weight: 600;
}

/* center the placeholder when it sits inside a card; in flex headers
   (.kid-header) the auto margin would otherwise push it to the middle of
   the row instead of staying flush with the info column (U1) */
.kid-card .kid-avatar-placeholder { margin: 0 auto; }

.kid-avatar-placeholder.lg {
    width: 96px;
    height: 96px;
    font-size: 2.5rem;
}

/* avatar edit block — pencil overlay on bottom-right of the avatar circle.
   the inner form holds the hidden file input + antiforgery token; clicking
   the pencil label triggers the file dialog and the form auto-submits on
   change. used on /kids/{id}/edit. */
.avatar-edit {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 1rem;
}
.avatar-preview {
    position: relative;
    width: 96px;
    height: 96px;
}
.avatar-preview img {
    width: 96px;
    height: 96px;
    border-radius: 50%;
    object-fit: cover;
    display: block;
}
/* size override only — keep base .kid-avatar-placeholder flex centering
   (otherwise the initial letter renders top-left instead of centered) */
.avatar-preview .kid-avatar-placeholder {
    width: 96px;
    height: 96px;
}
.avatar-edit-trigger {
    position: absolute;
    inset: auto 0 0 auto;
    margin: 0;
}
.avatar-pencil {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--color-primary);
    color: var(--color-text-inverse);
    border: 2px solid var(--color-bg);
    cursor: pointer;
    transition: background-color 0.15s;
}
.avatar-pencil:hover { background: var(--color-primary-hover, var(--color-primary)); }
/* visually hide the file input but keep it in the a11y tree and focusable
   via keyboard. a label[for] sits over the pencil button to handle clicks;
   keyboard users tab to the input itself, which renders the focus ring on
   the adjacent pencil via :has(). */
.avatar-file-input {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    opacity: 0;
    /* keep clip so the input doesn't hijack pointer events from the label */
    clip: rect(0 0 0 0);
}
.avatar-edit-trigger:has(.avatar-file-input:focus-visible) .avatar-pencil {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* RTL mirror: pencil sits on bottom-left in Hebrew, not bottom-right (design §20). */
[dir="rtl"] .avatar-edit-trigger {
    inset: auto auto 0 0;
}

/* avatar uploading state: same diameter, no layout jump. The image (or
   placeholder) fades, a 24px spinner sits centered on top. site.js flips
   .is-uploading on the .avatar-preview wrap when the inline form submits. */
.avatar-spinner {
    position: absolute;
    inset: 0;
    margin: auto;
    width: 24px;
    height: 24px;
    border: 2px solid var(--color-border);
    border-top-color: var(--color-primary);
    border-radius: 50%;
    animation: spin 0.6s linear infinite;
    pointer-events: none;
    display: none;
}

.avatar-preview.is-uploading .avatar-spinner { display: block; }

.avatar-preview.is-uploading > img,
.avatar-preview.is-uploading > .kid-avatar-placeholder {
    opacity: 0.45;
}

.kid-header {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    margin-bottom: 2rem;
}

.kid-header-info h1 {
    margin: 0 0 0.125rem;
}

.kid-header-info p {
    margin: 0 0 0.25rem;
    color: var(--color-text-secondary);
}

.kid-header-info a {
    font-size: 0.875rem;
}

/* --- Layout: Content + Sidebar --- */
.kid-layout {
    display: grid;
    grid-template-columns: 1fr;
    gap: 2rem;
}

@media (min-width: 1024px) {
    .kid-layout {
        grid-template-columns: 1fr 300px;
    }
}

/* --- Family group --- */
.family-group {
    margin-bottom: 2.5rem;
}

.family-group-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1rem;
    padding-bottom: 0.625rem;
    border-bottom: 1px solid var(--color-border-light);
}

.family-group-header h2 {
    font-size: 1.0625rem;
    font-weight: 600;
    margin: 0;
}

.family-group-header small {
    color: var(--color-text-muted);
    font-size: 0.8125rem;
}

.family-group-header-actions {
    display: flex;
    gap: 0.375rem;
}

/* --- Section title --- */
.section-title {
    font-size: 1rem;
    font-weight: 600;
    margin: 1.75rem 0 0.875rem;
    color: var(--color-text);
}

.section-title:first-child {
    margin-top: 0;
}

/* --- Add Memory Form --- */
.add-memory-card {
    margin-bottom: 1.5rem;
}

.add-memory-card form footer {
    display: flex;
    justify-content: flex-end;
    padding-top: 0.75rem;
}

/* --- Search --- */
.search-bar {
    margin-bottom: 1.5rem;
    position: relative;
}

.search-bar .htmx-indicator {
    position: absolute;
    right: 0.75rem;
    top: 50%;
    transform: translateY(-50%);
}

/* --- Timeline (connected, icon markers) --- */
.timeline {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    position: relative;
}

.timeline-connected {
    position: relative;
    padding: 0;
}

.timeline-connected::before {
    content: '';
    position: absolute;
    left: 19px;
    /* start at center of first marker (margin-top 0.375rem + half 40px marker = 0.375rem + 20px);
       stop at center of last marker (0.375rem + 20px from bottom), so the rail connects
       marker centers without dangling above or below the endpoints. */
    top: calc(0.375rem + 20px);
    bottom: calc(0.375rem + 20px + 1.5rem);
    width: 2px;
    background: var(--color-border);
    z-index: 0;
}

.timeline-entry {
    display: grid;
    grid-template-columns: 40px 1fr;
    column-gap: 1rem;
    margin-bottom: 1.5rem;
    position: relative;
}

.timeline-entry:last-child {
    margin-bottom: 0;
}

.timeline-marker {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--color-bg);
    border: 2px solid var(--color-border);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-secondary);
    z-index: 1;
    margin-top: 0.375rem;
    flex-shrink: 0;
    transition: border-color 0.15s, color 0.15s, box-shadow 0.15s;
}

.timeline-marker svg {
    width: 18px;
    height: 18px;
    display: block;
}

.timeline-entry:hover .timeline-marker {
    box-shadow: 0 0 0 4px var(--color-primary-light);
}

/* type-coded markers */
.type-text .timeline-marker {
    color: var(--color-primary);
    border-color: var(--color-primary);
}

.type-photo .timeline-marker {
    color: #f6a26b;
    border-color: #f6a26b;
}

.type-metric .timeline-marker {
    color: #4caf80;
    border-color: #4caf80;
}

.type-mixed .timeline-marker {
    color: #8a6bf3;
    border-color: #8a6bf3;
}

.type-birth .timeline-marker {
    color: var(--color-text-inverse);
    background: var(--color-primary);
    border-color: var(--color-primary);
}

.type-system .timeline-marker {
    color: var(--color-text-muted);
    border-color: var(--color-border);
    border-style: dashed;
}

.timeline-body {
    min-width: 0;
}

.timeline-meta {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    padding: 0.5rem 0.25rem 0;
    font-size: 0.8125rem;
    color: var(--color-text-muted);
}

.timeline-meta time {
    font-variant-numeric: tabular-nums;
}

.timeline-meta-end {
    display: inline-flex;
    align-items: baseline;
    gap: 0.5rem;
}

.memory-author-tag {
    display: inline-flex;
    align-items: center;
    padding: 0 0.4rem;
    height: 16px;
    border-radius: 999px;
    background: var(--color-bg-tertiary);
    color: var(--color-text-muted);
    font-size: 0.6875rem;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
}

.timeline-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.875rem;
    margin-bottom: 0.75rem;
    padding: 0 0.25rem;
    font-size: 0.75rem;
    color: var(--color-text-muted);
}

.timeline-legend span {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

.timeline-legend i {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 2px solid currentColor;
    background: transparent;
}

.timeline-legend span.type-text { color: var(--color-primary); }
.timeline-legend span.type-photo { color: #f6a26b; }
.timeline-legend span.type-metric { color: #4caf80; }
.timeline-legend span.type-mixed { color: #8a6bf3; }
.timeline-legend span small { color: var(--color-text-muted); }

/* --- Memory Item --- */
.memory-item {
    padding: 1.25rem;
    position: relative;
}

.timeline-connected .memory-item {
    padding: 1rem 1.125rem;
}

.memory-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.memory-header time {
    font-weight: 600;
    font-size: 0.9375rem;
}

.memory-header .age-at-memory {
    color: var(--color-text-muted);
    font-size: 0.8125rem;
}

.memory-actions {
    margin-left: auto;
    display: flex;
    gap: 0.25rem;
}

.memory-text {
    white-space: pre-wrap;
    margin-bottom: 0.75rem;
    line-height: 1.65;
}

.memory-content {
    line-height: 1.65;
    padding-right: 1.75rem;
}

.memory-content p {
    white-space: pre-wrap;
}

.memory-content p:not(:last-child) {
    margin-bottom: 0.5rem;
}

.memory-content .memory-metrics {
    margin-bottom: 0;
    background: transparent;
    padding: 0;
    font-size: 0.9375rem;
}

.memory-content .memory-photos {
    margin: 0.625rem 0 0;
}

.memory-content .memory-photos:first-child {
    margin-top: 0;
}

.memory-text { position: relative; display: flex; flex-direction: column; align-items: flex-start; }
.memory-content p.memory-text-preview,
.memory-content .memory-text-full { margin: 0; max-width: 100%; }
.memory-text .memory-text-toggle {
    display: none;
    background: none;
    border: 0;
    padding: 0;
    margin: 0.25rem 0 0;
    color: var(--color-primary);
    cursor: pointer;
    font: inherit;
    text-decoration: none;
    align-items: center;
    gap: 0.25rem;
}
.memory-text .memory-text-toggle:hover { color: var(--color-primary-hover); text-decoration: underline; }
.memory-text .label-less,
.memory-text.is-expanded .label-more { display: none; }
.memory-text.is-expanded .label-less { display: inline; }

/* clamp only when server flagged it as truncated and we're not yet expanded */
.memory-text.is-truncated:not(.is-expanded) .memory-text-preview {
    display: -webkit-box;
    -webkit-line-clamp: 6;
    line-clamp: 6;
    -webkit-box-orient: vertical;
    overflow: hidden;
    mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
    -webkit-mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
}
.memory-text.is-truncated .memory-text-toggle { display: inline-flex; }

/* hide preview when fully expanded with fetched content shown */
.memory-text.is-expanded.has-full .memory-text-preview { display: none; }
.memory-text .memory-text-full { display: none; white-space: pre-wrap; }
.memory-text .memory-text-full bdi { display: block; }
.memory-text.is-expanded.has-full .memory-text-full { display: block; }

.memory-text-spinner.is-loading {
    display: inline-block;
    width: 0.9em;
    height: 0.9em;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: spin 0.6s linear infinite;
}

.memory-metrics {
    display: flex;
    gap: 1.5rem;
    margin-bottom: 0.75rem;
    padding: 0.625rem 0.75rem;
    background-color: var(--color-bg-secondary);
    border-radius: 6px;
    font-size: 0.9rem;
}

.memory-photos {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.memory-photo {
    display: block;
    position: relative;
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: 6px;
}

.memory-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.2s;
}

.memory-photo:hover img {
    transform: scale(1.05);
}

.memory-photo .photo-caption {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 0.25rem 0.5rem;
    background: rgba(0, 0, 0, 0.65);
    color: #fff;
    font-size: 0.6875rem;
    text-align: center;
}

.memory-photo--failed {
    background: var(--color-bg-secondary);
    border: 1px dashed var(--color-border);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-muted);
}

.memory-photo--failed svg {
    width: 32px;
    height: 32px;
    opacity: 0.5;
}

.memory-footer {
    margin-top: 0.75rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--color-border-light);
    font-size: 0.8125rem;
    color: var(--color-text-muted);
}

.memory-kebab {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: none;
    background: transparent;
    color: var(--color-text-muted);
    cursor: pointer;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.memory-kebab:hover {
    background: var(--color-bg-tertiary);
    color: var(--color-text);
}

.memory-kebab-menu {
    position: absolute;
    top: 2.25rem;
    right: 0.5rem;
    min-width: 140px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    box-shadow: var(--shadow-md);
    padding: 0.25rem;
    z-index: 50;
    display: none;
}

.memory-kebab-menu.open {
    display: block;
}

.memory-kebab-menu button,
.memory-kebab-menu a {
    display: block;
    width: 100%;
    text-align: start;
    padding: 0.5rem 0.625rem;
    border: none;
    background: transparent;
    color: var(--color-text);
    font-size: 0.875rem;
    border-radius: 6px;
    cursor: pointer;
}

.memory-kebab-menu button:hover,
.memory-kebab-menu a:hover {
    background: var(--color-bg-tertiary);
}

/* --- Memory Form (Edit) --- */
.memory-form {
    padding: 1.25rem;
    background-color: var(--color-bg-secondary);
}

.memory-form .form-actions {
    display: flex;
    gap: 0.5rem;
    justify-content: flex-end;
    padding-top: 0.75rem;
}

/* --- File Previews --- */
.file-preview-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
    gap: 0.5rem;
    margin-top: 0.5rem;
}

.file-preview-grid img {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: 6px;
}

.preview-thumb {
    max-width: 80px;
    border-radius: 6px;
}

/* --- File Picker (reusable multi-file uploader) --- */
.file-picker {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin-top: 0.5rem;
}

.file-picker--compact { gap: 0.5rem; }

.file-picker-grid--strip {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    gap: 0.5rem;
    list-style: none;
    padding: 0 0 0.25rem;
    margin: 0;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
}

.file-picker-grid--strip:empty {
    display: none;
}

.file-picker-item {
    position: relative;
    aspect-ratio: 1;
    border-radius: 8px;
    overflow: hidden;
    background: var(--color-surface-alt);
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    /* allow vertical page scroll; horizontal motion is reserved for reorder */
    touch-action: pan-y;
}

.file-picker-grid--strip > .file-picker-item {
    flex: 0 0 72px;
    width: 72px;
    height: 72px;
    border-radius: 6px;
    scroll-snap-align: start;
}

.file-picker-item img {
    -webkit-user-drag: none;
    pointer-events: none;
}

.file-picker-item .file-picker-remove {
    pointer-events: auto;
}

.file-picker-item img,
.file-picker-item .photo-ph {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.file-picker-item.is-dragging {
    opacity: 0.4;
    cursor: grabbing;
    /* let elementFromPoint hit-test reach the tile underneath the dragging one */
    pointer-events: none;
}

.file-picker-item.is-pending-remove {
    opacity: 0.3;
    filter: grayscale(0.6);
}

.file-picker-item.is-pending-remove img {
    filter: brightness(0.7);
}

.file-picker-remove {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 22px;
    height: 22px;
    border: none;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.6);
    color: #fff;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    opacity: 0;
    transition: opacity 0.12s ease;
}

.file-picker-grid--strip > .file-picker-item .file-picker-remove {
    width: 18px;
    height: 18px;
    top: 3px;
    right: 3px;
}

[dir="rtl"] .file-picker-remove {
    right: auto;
    left: 4px;
}

[dir="rtl"] .file-picker-grid--strip > .file-picker-item .file-picker-remove {
    right: auto;
    left: 3px;
}

.file-picker-item:hover .file-picker-remove,
.file-picker-item:focus-within .file-picker-remove,
.file-picker-remove:focus-visible {
    opacity: 1;
}

@media (hover: none) {
    /* touch: × always visible since hover doesn't fire */
    .file-picker-item .file-picker-remove { opacity: 0.85; }
}

.file-picker-drop-zone--bar {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    border: 1px dashed var(--color-border);
    border-radius: 8px;
    color: var(--color-text-secondary);
    font-size: 0.875rem;
    font-weight: 500;
    cursor: pointer;
    transition: border-color 0.12s, background 0.12s, color 0.12s;
}

.file-picker-drop-zone--bar:hover,
.file-picker-drop-zone--bar:focus-within {
    border-color: var(--color-primary);
    color: var(--color-text);
    background: var(--color-bg-secondary);
}

.file-picker-drop-zone--bar.is-drag-over {
    border-style: solid;
    border-color: var(--color-primary);
    background: var(--color-primary-light);
    color: var(--color-primary);
}

.file-picker-count {
    margin-inline-start: auto;
    font-size: 0.75rem;
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
    font-weight: 400;
    /* "2 / 10" reads left-to-right even inside RTL */
    unicode-bidi: plaintext;
}

/* photo skeleton: shimmer block used while a photo is processing.
   sizes itself to the host (.memory-photo / .file-picker-item). The host
   carries aria-busy="true" with an aria-label for screen readers, so the
   bare .photo-ph element does not need its own aria attributes. */
.photo-ph {
    width: 100%;
    height: 100%;
    aspect-ratio: 1;
    border-radius: 6px;
    background:
        linear-gradient(110deg,
            var(--color-bg-secondary) 30%,
            var(--color-bg-tertiary) 50%,
            var(--color-bg-secondary) 70%);
    background-size: 200% 100%;
    animation: ph-shimmer 1.4s linear infinite;
    display: flex;
    align-items: center;
    justify-content: center;
}

@keyframes ph-shimmer {
    0%   { background-position: 100% 0; }
    100% { background-position: -100% 0; }
}

/* the global [aria-busy=true]::before injects an inline-block spinner that
   conflicts with positioned spinners inside these components, so suppress it
   on busy hosts that render their own indicator. */
.memory-photo[aria-busy="true"]::before,
.file-picker-item[aria-busy="true"]::before,
.avatar-preview[aria-busy="true"]::before {
    content: none;
}

/* --- Avatar Preview --- */
.avatar-preview img {
    max-width: 120px;
    border-radius: 50%;
    margin-top: 0.5rem;
}

/* --- Growth Stats --- */
.growth-stats {
    position: sticky;
    top: calc(56px + 1.5rem);
}

.current-stats {
    display: flex;
    gap: 2rem;
    margin-bottom: 1.5rem;
}

.stat {
    text-align: center;
}

.stat-value {
    display: block;
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

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

.stat small {
    display: block;
    color: var(--color-text-muted);
    font-size: 0.75rem;
}

.chart-container {
    margin-bottom: 1.5rem;
}

.chart-container h4 {
    margin-bottom: 0.5rem;
    font-size: 0.875rem;
    font-weight: 500;
}

.chart-container canvas,
.chart-container svg,
.chart-container .chart-svg {
    max-height: 150px;
    width: 100%;
    height: 80px;
    display: block;
}

/* --- Permissions list --- */
.perm-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.perm-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.875rem;
    padding: 0.75rem 1rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 8px;
}

/* family rows host an edit-in-place form below the view cluster, so they
   stack vertically. .perm-row-view replicates the default row's horizontal
   layout for the view state. other /access /permissions rows don't use
   [data-family-row] and keep the default .perm-row layout untouched. */
[data-family-row] {
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
}

.perm-row-view {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.875rem;
}

/* rename edit-in-place: form is hidden in view mode, replaces the view in edit mode */
.perm-row-edit { display: none; }
[data-family-row].is-editing .perm-row-view { display: none; }
[data-family-row].is-editing .perm-row-edit {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    width: 100%;
}
.perm-row-edit input[name="name"] {
    flex: 1 1 auto;
    min-width: 0;
}
.perm-row-edit-actions {
    display: flex;
    gap: 0.375rem;
    flex-shrink: 0;
}

/* small icon-only button used for the row pencil */
.btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    background: transparent;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    color: var(--color-text-secondary);
    cursor: pointer;
}
.btn-icon:hover { background: var(--color-bg-tertiary); color: var(--color-text); }

.perm-row-info {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-width: 0;
}

.perm-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--color-primary);
    color: var(--color-text-inverse);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.875rem;
    font-weight: 600;
    flex-shrink: 0;
}

.perm-row-text {
    min-width: 0;
}

.perm-row-text strong {
    display: block;
    font-size: 0.9375rem;
    line-height: 1.3;
}

.perm-row-text small {
    color: var(--color-text-muted);
    font-size: 0.8125rem;
}

.perm-row-actions {
    display: flex;
    gap: 0.375rem;
    align-items: center;
}

/* --- Role badge --- */
.role-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.1875rem 0.5rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1.2;
    letter-spacing: 0.01em;
}

.role-badge.read {
    background: var(--color-bg-tertiary);
    color: var(--color-text-secondary);
}

.role-badge.write {
    background: var(--color-primary-light);
    color: var(--color-primary);
}

.role-badge.owner {
    background: var(--color-bg-tertiary);
    color: var(--color-text);
    font-weight: 600;
}

.role-badge.pending {
    background: var(--color-bg-tertiary);
    color: var(--color-text-muted);
    border: 1px dashed var(--color-border);
}

/* --- Invite link box --- */
.invite-link-box {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 0.75rem;
    background: var(--color-bg-secondary);
    border: 1px dashed var(--color-border);
    border-radius: 6px;
    margin-top: 0.625rem;
}

.invite-link-text {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: ui-monospace, SFMono-Regular, "SF Mono", monospace;
    font-size: 0.8125rem;
    color: var(--color-text-secondary);
}

.invite-link-meta {
    margin-top: 0.375rem;
    font-size: 0.75rem;
    color: var(--color-text-muted);
}

/* --- Tabs --- */
.tabs {
    display: flex;
    gap: 0.5rem;
    border-bottom: 1px solid var(--color-border);
    margin-bottom: 1.5rem;
    overflow-x: auto;
    overflow-y: hidden;
}

.tab {
    padding: 0.5rem 0.75rem;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    color: var(--color-text-secondary);
    font-size: 0.875rem;
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
}

.tab:hover {
    color: var(--color-text);
}

.tab.active {
    color: var(--color-text);
    border-bottom-color: var(--color-primary);
}

/* --- Toggle switch --- */
.toggle {
    position: relative;
    display: inline-block;
    width: 38px;
    height: 22px;
    flex-shrink: 0;
}

.toggle input {
    opacity: 0;
    width: 0;
    height: 0;
}

.toggle-slider {
    position: absolute;
    inset: 0;
    background: var(--color-border);
    border-radius: 999px;
    cursor: pointer;
    transition: background 0.15s;
}

.toggle-slider::before {
    content: '';
    position: absolute;
    width: 18px;
    height: 18px;
    left: 2px;
    top: 2px;
    background: var(--color-bg);
    border-radius: 50%;
    transition: transform 0.15s;
    box-shadow: var(--shadow-sm);
}

.toggle input:checked + .toggle-slider {
    background: var(--color-primary);
}

.toggle input:checked + .toggle-slider::before {
    transform: translateX(16px);
}

/* --- Setting row --- */
.setting-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.875rem 0;
    border-bottom: 1px solid var(--color-border-light);
}

.setting-row:last-child {
    border-bottom: 0;
}

.setting-row-label strong {
    display: block;
    font-size: 0.9375rem;
    font-weight: 500;
    line-height: 1.4;
}

.setting-row-label small {
    color: var(--color-text-muted);
    font-size: 0.8125rem;
}

/* --- Empty state --- */
.empty-state {
    text-align: center;
    padding: 3rem 1.5rem;
    color: var(--color-text-muted);
}

.empty-card {
    padding: 3rem 1.5rem;
    text-align: center;
}

.empty-card .empty-icon {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--color-bg-tertiary);
    color: var(--color-text-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 1rem;
}

.empty-card h3 {
    margin-bottom: 0.5rem;
}

.empty-card p {
    color: var(--color-text-secondary);
    margin-bottom: 1.5rem;
    max-width: 360px;
    margin-inline: auto;
}

.timeline-empty-search {
    padding: 1.25rem 1rem;
    text-align: center;
    color: var(--color-text-secondary);
    background: var(--color-bg-secondary);
    border: 1px dashed var(--color-border);
    border-radius: 8px;
}

.timeline-empty-search p {
    margin: 0;
}

/* --- Notice / Toast --- */
.notice {
    padding: 0.75rem 0.875rem;
    border-radius: 8px;
    font-size: 0.875rem;
    margin-bottom: 1rem;
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
}

/* notice has display:flex which overrides the UA [hidden]→display:none.
   Restore it so the empty placeholder banner stays invisible until the
   client validator unsets the attribute (D3). */
.notice[hidden] { display: none; }

.notice.success {
    background: rgba(22, 163, 74, 0.08);
    color: var(--color-success);
    border: 1px solid rgba(22, 163, 74, 0.2);
}

.notice.info {
    background: var(--color-primary-light);
    color: var(--color-primary);
    border: 1px solid rgba(37, 99, 235, 0.18);
}

.notice.danger {
    background: rgba(220, 38, 38, 0.08);
    color: var(--color-danger);
    border: 1px solid rgba(220, 38, 38, 0.2);
}

.notice.warning {
    background: rgba(217, 119, 6, 0.08);
    color: #b45309;
    border: 1px solid rgba(217, 119, 6, 0.25);
}

[data-theme="dark"] .notice.warning {
    color: #fbbf24;
}

/* --- Login screen --- */
/* gradient lives on body so it fills the full viewport edge-to-edge;
   .app-main padding is zeroed out and .login-screen just centers its card */
body.login-page {
    background-image:
        radial-gradient(at 20% 10%, var(--color-primary-light) 0%, transparent 50%),
        radial-gradient(at 80% 80%, var(--color-primary-light) 0%, transparent 50%);
}

body.login-page .app-main {
    padding: 0;
}

.login-screen {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1 0 auto;
    width: 100%;
    /* leave room for the 56px brand+lang strip rendered by the global header */
    min-height: calc(100dvh - 56px);
    padding: 2rem;
}

.login-card {
    width: 100%;
    max-width: 380px;
    text-align: center;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 14px;
    padding: 2.5rem 2rem;
    box-shadow: var(--shadow-md);
}

.login-card h1 {
    font-size: 1.5rem;
    margin-bottom: 0.375rem;
}

.login-card p {
    color: var(--color-text-secondary);
    font-size: 0.9375rem;
    margin-bottom: 2rem;
}

.login-card .legal {
    margin-top: 1.5rem;
    font-size: 0.75rem;
    color: var(--color-text-muted);
    line-height: 1.5;
}

/* horizontal rule with centered label, e.g. "OR" between sign-in options.
   uses flex + ::before/::after lines so it stays centered regardless of label width. */
.or-separator {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 0.875rem 0;
    color: var(--color-text-muted);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.or-separator::before,
.or-separator::after {
    content: "";
    flex: 1;
    border-top: 1px solid var(--color-border-light);
}

.or-separator[hidden] { display: none; }

/* --- Invite landing --- */
.invite-landing {
    text-align: center;
    padding: 3rem 1.5rem 2rem;
    max-width: 480px;
    margin: 2rem auto;
}

.invite-landing .kid-avatar-placeholder {
    width: 96px;
    height: 96px;
    font-size: 2.5rem;
    margin-bottom: 1.5rem;
}

.invite-landing h1 {
    margin-bottom: 0.5rem;
}

.invite-landing p {
    color: var(--color-text-secondary);
    margin-bottom: 1.5rem;
}

.invite-landing .role-badge {
    margin-bottom: 1.5rem;
    font-size: 0.8125rem;
    padding: 0.25rem 0.625rem;
}

.invite-meta {
    margin-top: 1.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--color-border-light);
    font-size: 0.8125rem;
    color: var(--color-text-muted);
}

/* --- Language switcher --- */
.lang-switcher {
    position: relative;
}

.lang-switcher-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    height: 36px;
    padding: 0 0.625rem;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    background: transparent;
    color: var(--color-text-secondary);
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.lang-switcher-btn:hover {
    color: var(--color-text);
    background: var(--color-bg-tertiary);
}

.lang-switcher-btn svg {
    width: 14px;
    height: 14px;
}

.lang-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 180px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    box-shadow: var(--shadow-md);
    padding: 0.25rem;
    z-index: 200;
    display: none;
}

.lang-menu.open {
    display: block;
}

.lang-menu a,
.lang-menu button {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 0.5rem 0.625rem;
    border: none;
    background: transparent;
    border-radius: 6px;
    color: var(--color-text);
    font-size: 0.875rem;
    text-decoration: none;
    gap: 1rem;
    cursor: pointer;
    text-align: start;
}

.lang-menu a:hover,
.lang-menu button:hover {
    background: var(--color-bg-tertiary);
    color: var(--color-text);
}

.lang-menu a.active,
.lang-menu button.active {
    color: var(--color-primary);
    background: var(--color-primary-light);
}

.lang-menu a small,
.lang-menu button small {
    color: var(--color-text-muted);
    font-weight: 400;
}

.lang-menu a.active small,
.lang-menu button.active small {
    color: var(--color-primary);
}

/* --- PWA install prompt --- */
.pwa-prompt {
    position: relative;
    margin-top: 1rem;
    display: none;
    align-items: center;
    gap: 0.875rem;
    padding: 0.875rem 1rem;
    background: var(--color-primary-light);
    border: 1px solid var(--color-border);
    border-radius: 10px;
}

.pwa-prompt.visible {
    display: flex;
}

.pwa-prompt-icon {
    width: 36px;
    height: 36px;
    border-radius: 8px;
    background: var(--color-primary);
    color: var(--color-text-inverse);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-weight: 700;
    overflow: hidden;
}

.pwa-prompt-icon img {
    width: 22px;
    height: 22px;
    display: block;
}

.pwa-prompt-text {
    flex: 1;
    font-size: 0.875rem;
}

.pwa-prompt-text strong {
    display: block;
}

.pwa-prompt-text small {
    color: var(--color-text-muted);
}

.pwa-prompt-dismiss {
    background: transparent;
    border: none;
    color: var(--color-text-muted);
    cursor: pointer;
    padding: 0.25rem;
}

.pwa-prompt-dismiss:hover {
    color: var(--color-text);
}

/* --- Load More --- */
.load-more {
    text-align: center;
    padding: 1rem;
}

/* --- Misc --- */
.flex-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.spacer {
    flex: 1;
}

.divider {
    border: 0;
    border-top: 1px solid var(--color-border-light);
    margin: 1.5rem 0;
}

/* --- Utilities --- */
.text-muted {
    color: var(--color-text-muted);
}

.text-secondary {
    color: var(--color-text-secondary);
}

/* --- HTMX loading indicator --- */
.htmx-indicator {
    display: none;
}

.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
    display: inline-block;
}

[aria-busy="true"]::before {
    content: '';
    display: inline-block;
    width: 1em;
    height: 1em;
    border: 2px solid var(--color-border);
    border-top-color: var(--color-primary);
    border-radius: 50%;
    animation: spin 0.6s linear infinite;
    margin-right: 0.5em;
    vertical-align: middle;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

/* --- Form footer --- */
.form-actions {
    display: flex;
    gap: 0.5rem;
    padding-top: 0.75rem;
}

/* Edit Kid: Save sits inside the edit form, Delete is a sibling form below.
   Pull Delete up onto the same flex row as Save and push it to the far edge
   so the layout matches design §7 (justify-content: space-between). */
.kid-edit-actions {
    justify-content: flex-start;
}
.kid-edit-delete-form {
    margin-top: -2.75rem; /* aligns top with Save row (form-actions padding-top + button height baseline) */
    display: flex;
    justify-content: flex-end;
    margin-bottom: 0;
}

/* ===========================
   RTL adjustments
   =========================== */
[dir="rtl"] .timeline-connected::before {
    left: auto;
    right: 19px;
    /* mirror the LTR top/bottom offsets */
}

/* In RTL, CSS Grid reverses column visual order: column 1 renders on the right,
   column 2 on the left. So we keep the template as 40px 1fr (marker col first =
   visually right), let both items stay at their natural column positions (marker
   col 1 = right, body col 2 = left), and the rail right:19px aligns with the
   center of that 40px column on the right edge. */
[dir="rtl"] .timeline-entry {
    grid-template-columns: 40px 1fr;
}

[dir="rtl"] .timeline-marker {
    grid-column: 1;
    grid-row: 1;
}

[dir="rtl"] .timeline-body {
    grid-column: 2;
    grid-row: 1;
}

[dir="rtl"] .memory-kebab,
[dir="rtl"] .memory-kebab-menu {
    right: auto;
    left: 0.5rem;
}

[dir="rtl"] .memory-content {
    padding-right: 0;
    padding-left: 1.75rem;
}

[dir="rtl"] .memory-actions {
    margin-left: 0;
    margin-right: auto;
}

[dir="rtl"] .lang-menu {
    right: auto;
    left: 0;
}

[dir="rtl"] .back-link::before {
    content: '\2192';
}

[dir="rtl"] .toggle-slider::before {
    left: auto;
    right: 2px;
}

[dir="rtl"] .toggle input:checked + .toggle-slider::before {
    transform: translateX(-16px);
}

[dir="rtl"] .perm-row-actions,
[dir="rtl"] .form-actions,
[dir="rtl"] .kid-card-actions,
[dir="rtl"] .family-group-header-actions {
    flex-direction: row-reverse;
}

[dir="rtl"] .invite-link-text {
    direction: ltr;
    text-align: right;
}

[dir="rtl"] input[type="email"],
[dir="rtl"] input[type="url"],
[dir="rtl"] input[type="tel"] {
    direction: ltr;
    text-align: right;
}

/* preserve LTR for time/numbers in RTL */
[dir="rtl"] time,
[dir="rtl"] .stat-value {
    unicode-bidi: plaintext;
}

/* mobile reflow: Growth above timeline (U20). Below the lg breakpoint
   the .kid-layout grid stacks; reorder so the aside (Growth) renders
   first, and unset its sticky positioning which has no value when stacked. */
@media (max-width: 1023px) {
    .kid-layout > aside { order: -1; }
    .kid-layout > aside .growth-stats { position: static; }
}

/* user menu (replaces lang switcher + email + logout + theme toggle in the
   header right strip — directive D1). One trigger button, one panel. */
.user-menu { position: relative; display: flex; align-items: center; }

.user-menu-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem 0.625rem;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 8px;
    color: var(--color-text);
    font: inherit;
    cursor: pointer;
    max-width: 18ch;
}

.user-menu-btn:hover { background: var(--color-bg-secondary); }

.user-menu-email {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.875rem;
}

.user-menu-panel {
    position: absolute;
    top: calc(100% + 0.5rem);
    right: 0;
    min-width: 240px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    box-shadow: var(--shadow-md);
    padding: 0.375rem;
    display: none;
    z-index: 50;
}

[dir="rtl"] .user-menu-panel { right: auto; left: 0; }

.user-menu-panel.open { display: block; }

/* explicitly include button[type="submit"].user-menu-item so it beats the
   global button[type=submit]→primary-blue rule on specificity */
.user-menu-item,
button[type="submit"].user-menu-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    width: 100%;
    padding: 0.5rem 0.625rem;
    background: transparent;
    border: 0;
    border-radius: 6px;
    color: var(--color-text);
    font: inherit;
    font-size: 0.875rem;
    text-align: start;
    text-decoration: none;
    cursor: pointer;
}

.user-menu-item:hover,
.user-menu-item:focus-visible,
button[type="submit"].user-menu-item:hover { background: var(--color-bg-secondary); }

.user-menu-item-danger,
button[type="submit"].user-menu-item-danger { color: var(--color-danger); border-color: transparent; }
.user-menu-item-danger:hover,
button[type="submit"].user-menu-item-danger:hover { background: rgba(220, 38, 38, 0.08); color: var(--color-danger); }

.user-menu-toggle-row { width: 100%; }

.user-menu-toggle-state {
    display: inline-flex;
    align-items: center;
    color: var(--color-text-secondary);
}

.user-menu-section {
    padding: 0.375rem 0.625rem 0.5rem;
}

.user-menu-section-label {
    font-size: 0.75rem;
    color: var(--color-text-muted);
    margin-bottom: 0.375rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.user-menu-lang-row {
    display: flex;
    gap: 0.25rem;
}

/* explicit button[type=submit] override so the global submit→primary rule
   doesn't paint these blue */
.user-menu-lang-btn,
button[type="submit"].user-menu-lang-btn {
    flex: 1;
    padding: 0.375rem 0;
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border);
    border-radius: 6px;
    color: var(--color-text-secondary);
    font: inherit;
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
}

.user-menu-lang-btn:hover,
button[type="submit"].user-menu-lang-btn:hover {
    background: var(--color-bg-tertiary);
    color: var(--color-text);
    border-color: var(--color-border);
}

.user-menu-lang-btn.active,
button[type="submit"].user-menu-lang-btn.active {
    background: var(--color-primary-light);
    color: var(--color-primary);
    border-color: var(--color-primary);
}

.user-menu-separator {
    height: 1px;
    background: var(--color-border-light);
    margin: 0.375rem 0;
}

/* memory metric values shouldn't break across lines on mobile (M1). */
.memory-metrics span { white-space: nowrap; }


/* confirm dialog (replaces native confirm()).
   position:fixed + inset:0 + margin:auto pins centering regardless of the
   body's flex layout — without it, the body's `display:flex; flex-direction:column`
   makes a top-level <dialog> a flex item and pushes it off-center. */
.modal-dialog {
    position: fixed;
    inset: 0;
    margin: auto;
    border: 1px solid var(--color-border);
    border-radius: 12px;
    background: var(--color-surface);
    color: var(--color-text);
    padding: 0;
    box-shadow: var(--shadow-md);
    max-width: 420px;
    width: calc(100vw - 2rem);
    height: max-content;
    max-height: calc(100vh - 2rem);
}

.modal-dialog::backdrop {
    background: rgba(15, 17, 23, 0.45);
    backdrop-filter: blur(2px);
}

.modal-form {
    padding: 1.25rem;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.modal-form h2 {
    margin: 0;
    font-size: 1.125rem;
    font-weight: 600;
}

.modal-form p {
    margin: 0;
    color: var(--color-text-secondary);
    line-height: 1.5;
}

.modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 0.5rem;
}

[dir="rtl"] .modal-actions {
    flex-direction: row-reverse;
}

/* toast region for transient success/error feedback (replaces alert()) */
.toast-region {
    position: fixed;
    bottom: 1rem;
    right: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    z-index: 1000;
    pointer-events: none;
}

[dir="rtl"] .toast-region {
    right: auto;
    left: 1rem;
}

.toast {
    pointer-events: auto;
    min-width: 240px;
    max-width: 360px;
    padding: 0.75rem 1rem;
    border-radius: 8px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    box-shadow: var(--shadow-md);
    font-size: 0.9375rem;
    line-height: 1.4;
    color: var(--color-text);
    animation: toast-in 0.18s ease-out;
}

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

.toast.toast-success {
    border-color: var(--color-success);
    color: var(--color-success);
    background: var(--color-bg-secondary);
}

.toast.dismissing {
    animation: toast-out 0.18s ease-in forwards;
}

@keyframes toast-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes toast-out {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(8px); }
}

/* photo lightbox dialog */
.lightbox-dialog {
    position: fixed;
    inset: 0;
    margin: auto;
    padding: 0;
    border: none;
    background: transparent;
    width: 100dvw;
    height: 100dvh;
    max-width: 100dvw;
    max-height: 100dvh;
    /* display:none when closed (UA default); flex only when open */
    display: none;
    align-items: center;
    justify-content: center;
}

.lightbox-dialog[open] {
    display: flex;
}

.lightbox-dialog::backdrop {
    background: rgba(0, 0, 0, 0.88);
    backdrop-filter: blur(4px);
}

.lightbox-img-wrap {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    max-width: calc(100dvw - 8rem);
    max-height: calc(100dvh - 4rem);
}

.lightbox-spinner {
    position: absolute;
    inset: 0;
    margin: auto;
    width: 32px;
    height: 32px;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: #fff;
    border-radius: 50%;
    animation: spin 0.6s linear infinite;
    display: none;
}

.lightbox-img-wrap.is-loading .lightbox-spinner { display: block; }

.lightbox-img {
    display: block;
    max-width: 100%;
    max-height: calc(100dvh - 4rem);
    object-fit: contain;
    border-radius: 6px;
    box-shadow: 0 8px 40px rgba(0, 0, 0, 0.6);
    transition: opacity 0.15s;
}

.lightbox-img.loading {
    opacity: 0.4;
}

.lightbox-close {
    position: fixed;
    top: 1rem;
    right: 1rem;
    width: 40px;
    height: 40px;
    padding: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.15);
    border: 1px solid rgba(255, 255, 255, 0.25);
    color: #fff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10;
    backdrop-filter: blur(4px);
}

.lightbox-close:hover { background: rgba(255, 255, 255, 0.25); }

.lightbox-nav {
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
    width: 44px;
    height: 44px;
    padding: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.15);
    border: 1px solid rgba(255, 255, 255, 0.25);
    color: #fff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10;
    backdrop-filter: blur(4px);
    transition: background 0.15s;
}

.lightbox-nav:hover { background: rgba(255, 255, 255, 0.28); }
.lightbox-nav[hidden] { display: none; }

.lightbox-prev { left: 1rem; }
.lightbox-next { right: 1rem; }

[dir="rtl"] .lightbox-close { right: auto; left: 1rem; }
[dir="rtl"] .lightbox-prev { left: auto; right: 1rem; }
[dir="rtl"] .lightbox-next { right: auto; left: 1rem; }

.lightbox-counter {
    position: fixed;
    bottom: 1rem;
    left: 50%;
    transform: translateX(-50%);
    color: rgba(255, 255, 255, 0.75);
    font-size: 0.875rem;
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}

.lightbox-counter[hidden] { display: none; }

/* make thumbnail links not open new tab when lightbox handles them */
a[data-lightbox-src] { cursor: zoom-in; }

/* small numeric pill that sits beside a label. used to surface counts the
   user would otherwise miss (pending invites). only rendered when count > 0. */
.nav-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    margin-inline-start: 0.375rem;
    border-radius: 999px;
    background: var(--color-primary);
    color: var(--color-text-inverse);
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    vertical-align: 1px;
}

/* ===========================
   Step-up auth (verify view)
   =========================== */

/* circular icon above the verify card heading */
.step-up-icon {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--color-primary-light);
    color: var(--color-primary);
    margin: 0 auto 1rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* the OTP input — single text field, not 6 boxes.
   letter-spacing + tabular-nums make it read as a code. */
.otp-input {
    width: 100%;
    text-align: center;
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
    font-size: 1.5rem;
    font-weight: 600;
    letter-spacing: 0.5em;
    text-indent: 0.5em; /* visually re-center given the trailing letter-spacing slot */
    font-variant-numeric: tabular-nums;
    padding: 0.75rem 0.5rem;
    margin: 0.25rem 0 0;
}

.otp-input::placeholder {
    color: var(--color-text-muted);
    font-weight: 400;
    letter-spacing: 0.35em;
}

.otp-input:disabled {
    background: var(--color-bg-secondary);
    color: var(--color-text-muted);
    cursor: not-allowed;
}

.otp-input--error {
    border-color: var(--color-danger);
}

/* secondary-action row under the primary button */
.step-up-secondary {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

.step-up-divider {
    color: var(--color-text-muted);
    font-size: 0.75rem;
}

/* /docs/api reference tables. minimal styling — content-first; fits the page
   layout without competing with kid timeline / settings table styling. */
.docs-table {
    width: 100%;
    border-collapse: collapse;
    margin: 0.75rem 0;
    font-size: 0.875rem;
}

.docs-table th,
.docs-table td {
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--color-border);
    text-align: start;
    vertical-align: top;
}

.docs-table th {
    background: var(--color-bg-secondary);
    font-weight: 600;
}

.docs-table code {
    font-size: 0.8125rem;
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* === API access (settings#api) — secret card + perm-row variants === */
.perm-row.is-revoked { opacity: 0.6; }
.perm-row.is-revoked .perm-row-text strong { text-decoration: line-through; }

/* devices-footer: "{N} active · Register this device" line below the list.
   wraps a <form> inline; needs explicit inline-flex so the <form>'s default
   block display doesn't kick the submit button onto its own line. */
.devices-footer {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin: 0.75rem 0 0;
    font-size: 0.8125rem;
}
.devices-footer form { display: inline; margin: 0; }
.devices-footer form[hidden] { display: none; }

/* device-row inline rename: same toggle pattern as [data-family-row].is-editing
   but driven by [data-device-row].is-editing. view nodes hide; edit nodes (input
   + Save + Cancel) appear in the same slots. no CSS class is on the buttons —
   we toggle via the [data-device-view] / [data-device-edit] markers. */
[data-device-row] [data-device-edit] { display: none; }
[data-device-row].is-editing [data-device-view] { display: none; }
[data-device-row].is-editing [data-device-edit] { display: inline-flex; }
[data-device-row].is-editing .device-rename-form { display: block; }
[data-device-row].is-editing .device-rename-form input[name="friendlyName"] {
    width: 100%;
    font-size: 0.9375rem;
    margin: 0;
}

.perm-avatar.is-icon {
    background: rgba(37, 99, 235, 0.12);
    color: var(--color-primary);
}

.perm-avatar.is-icon.is-neutral {
    background: var(--color-bg-secondary);
    color: var(--color-text-secondary);
}

.secret-card {
    background: rgba(214, 134, 38, 0.06);
    border: 1px solid rgba(214, 134, 38, 0.32);
    border-radius: 10px;
    padding: 1rem 1.125rem;
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    margin-bottom: 1rem;
}

.secret-card-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: #a35a14;
    font-weight: 600;
    font-size: 0.875rem;
}

[data-theme="dark"] .secret-card-head { color: #f3b07c; }

.secret-card-body {
    color: var(--color-text-secondary);
    font-size: 0.8125rem;
    line-height: 1.5;
}

.secret-card-field-label {
    display: block;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--color-text-secondary);
    margin-bottom: 0.25rem;
}

.secret-value {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    padding: 0.5rem 0.625rem;
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
    font-size: 0.8125rem;
    color: var(--color-text);
    word-break: break-all;
}

.secret-value > code { flex: 1; }

.secret-value button { flex-shrink: 0; }

.secret-card-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
}

.secret-copied {
    color: var(--color-success);
    font-size: 0.75rem;
    margin-inline-start: 0.25rem;
}

/* === /docs/api page === */
.docs-page h2 {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--color-text);
    margin: 1.75rem 0 0.625rem;
    padding-bottom: 0.375rem;
    border-bottom: 1px solid var(--color-border);
}

.docs-page h2:first-child { margin-top: 0; }

.docs-page p {
    margin: 0 0 0.875rem;
    line-height: 1.65;
    color: var(--color-text);
}

.docs-page ul,
.docs-page ol {
    margin: 0 0 1rem;
    padding-inline-start: 1.25rem;
    line-height: 1.7;
    color: var(--color-text);
}

.docs-page li { margin-bottom: 0.375rem; }
.docs-page li:last-child { margin-bottom: 0; }

.docs-page code {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
    font-size: 0.8125rem;
    background: var(--color-bg-secondary);
    padding: 0.0625rem 0.375rem;
    border-radius: 4px;
    color: var(--color-text);
}

.docs-page .docs-note {
    background: rgba(214, 134, 38, 0.06);
    border: 1px solid rgba(214, 134, 38, 0.25);
    border-radius: 8px;
    padding: 0.625rem 0.875rem;
    font-size: 0.8125rem;
    color: var(--color-text-secondary);
    margin-bottom: 1rem;
}

.docs-layout {
    display: flex;
    gap: 2rem;
    flex-wrap: wrap;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 12px;
    padding: 1.5rem;
}

.docs-toc {
    flex: 0 0 200px;
    font-size: 0.8125rem;
    line-height: 2;
    align-self: flex-start;
    position: sticky;
    top: 1.5rem;
}

.docs-toc strong {
    display: block;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text-muted);
    margin-bottom: 0.5rem;
}

.docs-toc a {
    display: block;
    color: var(--color-text-secondary);
    text-decoration: none;
}

.docs-toc a:hover,
.docs-toc a.is-active {
    color: var(--color-primary);
}

.docs-page {
    flex: 1;
    min-width: 280px;
}

@media (max-width: 720px) {
    .docs-layout { padding: 1rem; gap: 1rem; }
    .docs-toc { position: static; flex-basis: 100%; }
}

/* === OAuth flow strip === */
.oauth-flow {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 0.625rem;
    margin: 0.5rem 0 1rem;
}

.oauth-flow-step {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 10px;
    padding: 0.875rem;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.oauth-flow-step .num {
    width: 22px;
    height: 22px;
    border-radius: 11px;
    background: var(--color-primary);
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    font-weight: 700;
}

.oauth-flow-step strong { font-size: 0.875rem; color: var(--color-text); }
.oauth-flow-step small  { font-size: 0.75rem; color: var(--color-text-secondary); line-height: 1.5; }

/* === Code samples (tabs + block + tokens) === */
.code-tabs {
    display: flex;
    gap: 0.25rem;
    border-bottom: 1px solid var(--color-border);
    margin-bottom: 0.625rem;
}

.code-tabs button {
    background: transparent;
    border: 0;
    padding: 0.375rem 0.625rem;
    font-size: 0.8125rem;
    color: var(--color-text-secondary);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}

.code-tabs button.active {
    color: var(--color-primary);
    border-bottom-color: var(--color-primary);
    font-weight: 600;
}

.code-block {
    background: var(--color-bg-secondary);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    padding: 0.875rem 1rem;
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
    font-size: 0.8125rem;
    color: var(--color-text);
    overflow-x: auto;
    line-height: 1.6;
    margin: 0 0 1rem;
    white-space: pre;
}

.code-block .tok-kw  { color: #c4359a; }
.code-block .tok-str { color: #2f7a4f; }
.code-block .tok-num { color: #a35a14; }
.code-block .tok-com { color: var(--color-text-muted); font-style: italic; }

[data-theme="dark"] .code-block .tok-kw  { color: #d480bd; }
[data-theme="dark"] .code-block .tok-str { color: #6fcc97; }
[data-theme="dark"] .code-block .tok-num { color: #f3b07c; }

.code-sample[hidden] { display: none; }

/* === Model reference === */
.model-ref {
    border: 1px solid var(--color-border);
    border-radius: 10px;
    overflow: hidden;
    background: var(--color-surface);
    margin-bottom: 1rem;
}

.model-ref-head {
    padding: 0.75rem 1rem;
    background: var(--color-bg-secondary);
    border-bottom: 1px solid var(--color-border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.model-ref-head h4 {
    margin: 0;
    font-size: 0.9375rem;
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
    font-weight: 600;
    color: var(--color-text);
}

.model-ref-head small {
    font-size: 0.75rem;
    color: var(--color-text-muted);
    font-family: 'Inter', -apple-system, system-ui, sans-serif;
    text-align: end;
}

.model-ref-row {
    display: grid;
    grid-template-columns: minmax(140px, 1fr) minmax(110px, 0.8fr) 2fr;
    gap: 0.875rem;
    padding: 0.625rem 1rem;
    border-top: 1px solid var(--color-border);
    align-items: baseline;
}

.model-ref-row:first-of-type { border-top: 0; }

.model-ref-row .field {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--color-text);
}

.model-ref-row .field .req {
    color: #c4359a;
    margin-inline-start: 0.125rem;
}

.model-ref-row .ftype {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
    font-size: 0.75rem;
    color: var(--color-text-muted);
}

.model-ref-row .fdesc {
    font-size: 0.8125rem;
    color: var(--color-text-secondary);
    line-height: 1.5;
}

@media (max-width: 560px) {
    .model-ref-row {
        grid-template-columns: 1fr;
        gap: 0.25rem;
    }
}


/* ── step-up dialog ──────────────────────────────────────────────────────── */
.step-up-dialog {
    position: fixed;
    inset: 0;
    margin: auto;
    border: 1px solid var(--color-border);
    border-radius: 12px;
    background: var(--color-surface);
    color: var(--color-text);
    padding: 0;
    box-shadow: var(--shadow-md);
    max-width: 420px;
    width: calc(100vw - 2rem);
    height: max-content;
    max-height: calc(100vh - 2rem);
}

.step-up-dialog::backdrop {
    background: rgba(15, 17, 23, 0.45);
    backdrop-filter: blur(2px);
}

.step-up-dialog-body {
    padding: 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.step-up-dialog-header {
    position: relative;
    text-align: center;
    margin-bottom: 0.25rem;
}

.step-up-dialog-header h2 {
    font-size: 1.125rem;
    font-weight: 600;
}

.step-up-dialog-close {
    position: absolute;
    top: -0.25rem;
    inset-inline-end: -0.25rem;
    background: transparent;
    border: none;
    color: var(--color-text-secondary);
    cursor: pointer;
    padding: 0.25rem;
    border-radius: 6px;
    line-height: 0;
}

.step-up-dialog-close:hover {
    color: var(--color-text);
    background: var(--color-bg-subtle, rgba(0, 0, 0, 0.04));
}

@media (max-width: 576px) {
    .step-up-dialog {
        max-width: 100vw;
        width: 100vw;
        max-height: 100vh;
        border-radius: 0;
    }
}
