/* ==========================================================================
   Design tokens
   Dark, high-contrast theme with a single warm accent. Built on top of
   Bootstrap 5.3's native dark mode (`data-bs-theme="dark"` on <html>) by
   overriding its CSS custom properties, rather than fighting the light
   theme with overrides everywhere - this keeps free-riding on Bootstrap's
   form/validation styling (bootstrap_5_layout.html.twig) intact.
   ========================================================================== */

:root,
[data-bs-theme='dark'] {
    /* Accent - warm amber, used for primary actions, links, focus rings */
    --accent-400: #f7b171;
    --accent-500: #f2994a;
    --accent-600: #d97f2e;
    --accent-rgb: 242, 153, 74;

    /* Chalk - pale seafoam used only in the documentation wiki, for
       annotation marks/dashed cut-lines/keycaps (like tailor's chalk
       against dark fabric). Never used for primary actions or links -
       those stay --accent everywhere, including inside the wiki. */
    --chalk-400: #b7e0da;
    --chalk-500: #8ecfc4;
    --chalk-rgb: 142, 207, 196;

    /* Surfaces */
    --surface-0: #0a0a0c;
    /* page background */
    --surface-1: #141417;
    /* card background */
    --surface-2: #1c1c20;
    /* raised / hovered surface */
    --border-subtle: rgba(255, 255, 255, 0.08);
    --border-strong: rgba(255, 255, 255, 0.16);

    --text-primary: #f2f2f0;
    --text-muted: #9a9aa2;

    color-scheme: dark;

    --bs-body-font-family: 'Inter Variable', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --bs-font-sans-serif: 'Inter Variable', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --bs-body-bg: var(--surface-0);
    --bs-body-color: var(--text-primary);
    --bs-secondary-color: var(--text-muted);
    --bs-tertiary-bg: var(--surface-1);
    --bs-secondary-bg: var(--surface-2);
    --bs-border-color: var(--border-subtle);
    --bs-border-color-translucent: var(--border-subtle);

    --bs-border-radius: 0.6rem;
    --bs-border-radius-lg: 1rem;
    --bs-border-radius-sm: 0.4rem;
    --bs-border-radius-xl: 1.25rem;

    --bs-primary: var(--accent-500);
    --bs-primary-rgb: var(--accent-rgb);
    --bs-primary-text-emphasis: var(--accent-400);
    --bs-primary-bg-subtle: #2a1f14;
    --bs-primary-border-subtle: #4a3520;
    --bs-link-color: var(--accent-400);
    --bs-link-color-rgb: var(--accent-rgb);
    --bs-link-hover-color: var(--accent-400);

    --bs-emphasis-color: #fff;
}

body {
    background: radial-gradient(ellipse 80% 50% at 50% -10%, #201a12 0%, transparent 60%), var(--surface-0);
    min-height: 100vh;
}

::selection {
    background: var(--accent-500);
    color: #14100a;
}

/* Off-screen until keyboard-focused, so sighted mouse users never see it but
   keyboard/screen-reader users can jump past the nav (which got a fair bit
   bigger once the tool switcher was added) straight to page content. */
.skip-link {
    position: absolute;
    top: -3rem;
    left: 1rem;
    z-index: 1090;
    padding: 0.6rem 1.1rem;
    border-radius: var(--bs-border-radius);
    background: var(--accent-500);
    color: #14100a;
    font-weight: 600;
    text-decoration: none;
    transition: top 0.15s ease;
}

.skip-link:focus {
    top: 1rem;
}

/* ==========================================================================
   Navbar
   ========================================================================== */

.navbar-app {
    background: rgba(10, 10, 12, 0.85);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--border-subtle);
}

.brand-mark {
    display: inline-flex;
    align-items: center;
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: -0.01em;
    color: var(--text-primary) !important;
}

.brand-mark-cos {
    color: var(--text-primary);
}

.brand-mark-faro {
    color: var(--accent-400);
}

.brand-mark-icon {
    width: 2.15rem;
    height: 2.15rem;
    margin-right: 0.55rem;
}

.navbar-app .nav-link {
    color: var(--text-muted);
    font-weight: 500;
}

.navbar-app .nav-link:hover {
    color: var(--text-primary);
}

.nav-tool-switcher-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: var(--bs-border-radius);
    color: var(--text-muted);
    background: transparent;
    border: 1px solid transparent;
    font-size: 1.1rem;
    line-height: 1;
    transition: color .15s ease, background-color .15s ease, border-color .15s ease;
}

.nav-tool-switcher-toggle:hover,
.nav-tool-switcher-toggle:focus-visible,
.nav-tool-switcher-toggle[aria-expanded="true"] {
    color: var(--text-primary);
    background: var(--surface-1);
    border-color: var(--border-subtle);
}

/* Bootstrap's .dropdown-toggle caret isn't used here - the apps-grid icon
   already reads as "switch/open", and a trailing caret would unbalance a
   button this small - so the caret markup is simply never added, rather
   than added and hidden. */

.nav-tool-switcher-menu-icon {
    display: block;
    flex-shrink: 0;
}

.pref-toggle {
    display: inline-flex;
    border: 1px solid var(--border-strong);
    border-radius: var(--bs-border-radius-pill);
    overflow: hidden;
}

.pref-toggle-option {
    /* Reset so this class renders identically whether it's still an <a>
       somewhere or, since the 2026-08 code review moved these to
       CSRF-protected POST forms, a <button> - neither browser's default
       button chrome (border/background) nor its font should show through. */
    appearance: none;
    background: none;
    border: none;
    font: inherit;
    cursor: pointer;
    padding: 0.2rem 0.6rem;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-muted);
    text-decoration: none;
}

.pref-toggle-option:hover {
    color: var(--text-primary);
}

.pref-toggle-option.active {
    background: var(--accent-500);
    color: #14100a;
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
    font-weight: 600;
    letter-spacing: 0.01em;
    padding-inline: 1.15rem;
}

/*
 * Bootstrap's precompiled CSS bakes theme colors into each button variant
 * as literal hex values on these --bs-btn-* custom properties (NOT as
 * var(--bs-primary) references) - overriding the root --bs-primary token
 * alone has no effect on .btn-primary. Every color has to be restated here
 * using our accent palette instead.
 */
.btn-primary {
    --bs-btn-color: #14100a;
    --bs-btn-bg: var(--accent-500);
    --bs-btn-border-color: var(--accent-500);
    --bs-btn-hover-color: #14100a;
    --bs-btn-hover-bg: var(--accent-400);
    --bs-btn-hover-border-color: var(--accent-400);
    --bs-btn-active-color: #14100a;
    --bs-btn-active-bg: var(--accent-600);
    --bs-btn-active-border-color: var(--accent-600);
    --bs-btn-focus-shadow-rgb: var(--accent-rgb);
    --bs-btn-disabled-bg: var(--accent-500);
    --bs-btn-disabled-border-color: var(--accent-500);
}

.btn-outline-primary {
    --bs-btn-color: var(--accent-400);
    --bs-btn-border-color: var(--accent-600);
    --bs-btn-hover-color: #14100a;
    --bs-btn-hover-bg: var(--accent-500);
    --bs-btn-hover-border-color: var(--accent-500);
    --bs-btn-active-color: #14100a;
    --bs-btn-active-bg: var(--accent-500);
    --bs-btn-active-border-color: var(--accent-500);
    --bs-btn-focus-shadow-rgb: var(--accent-rgb);
    --bs-btn-disabled-color: var(--accent-600);
}

.btn-lg {
    padding: 0.75rem 1.75rem;
    border-radius: var(--bs-border-radius-lg);
}

/* ==========================================================================
   Cards / surfaces
   ========================================================================== */

.card,
.panel {
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
}

.panel {
    border-radius: var(--bs-border-radius-lg);
    padding: 1.75rem;
}

.feature-card {
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
    border-radius: var(--bs-border-radius-lg);
    padding: 1.75rem;
    height: 100%;
    transition: border-color 0.15s ease, transform 0.15s ease;
}

.feature-card:hover {
    border-color: var(--border-strong);
    transform: translateY(-2px);
}

.feature-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 0.75rem;
    background: var(--bs-primary-bg-subtle);
    color: var(--accent-400);
    font-size: 1.3rem;
    margin-bottom: 1rem;
}

/* The 4 tools' own icon images (as opposed to the generic Bootstrap-icon
   glyphs .feature-icon otherwise holds for unrelated per-feature bullets
   on landing pages) - sized to fill most of the badge rather than sitting
   at glyph scale, since the artwork reads better bigger. */
.feature-icon img {
    width: 2.35rem;
    height: 2.35rem;
}

/* ==========================================================================
   Hero (home page)
   ========================================================================== */

.hero {
    padding: 6rem 0 4rem;
    text-align: center;
}

/* Homepage and all four tool landing pages: hero title sits directly
   below a right-aligned action toolbar and/or directly above a banner
   image, both of which bring their own margin - the plain .hero padding
   above was tuned for standalone use (no toolbar/image immediately
   adjacent) and doubles up with the surrounding <main class="py-5">
   padding here. */
.hero-top {
    padding: 1.5rem 0 2rem;
}

.hero-title {
    font-size: clamp(2.25rem, 5vw, 3.75rem);
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.08;
    margin-bottom: 1.25rem;
}

.gradient-text {
    background: linear-gradient(90deg, var(--accent-400), #f2c078 60%, #cfe0f5);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

/* All four tool landing pages (Poster Maker, Prop Scaler, Unfolder,
   Pattern Editor): same visual language as the homepage hero-banner below
   (full-width, rounded, a bottom scrim with a feature list overlaid on
   the image). Each page has its own *_hero_bg.webp, a render
   pre-composited on a dark background so it sits flush in the box with
   no mask needed. Reuses the homepage's .hero-banner-features list
   styling (and its sub-576px hidden state) directly, just in a
   tool-specific wrapper. */
.tool-hero-banner {
    position: relative;
    margin: 3rem auto 0;
    border-radius: var(--bs-border-radius-lg);
    overflow: hidden;
    border: 1px solid var(--border-subtle);
    aspect-ratio: 1915 / 821;
}

.tool-hero-banner-image {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.tool-hero-banner-scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(10, 10, 12, 0) 35%, rgba(10, 10, 12, .85) 100%);
}

/* Element-qualified (ul.___) so this outranks the later .hero-banner-features
   { padding: 0; } rule below - equal-specificity classes on the same element
   would otherwise let source order silently zero out this padding. */
ul.tool-hero-banner-features {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 0 clamp(1rem, 4vw, 3rem) clamp(0.6rem, 1.5vw, 1.1rem);
}

/* The homepage's six items wrap onto 2-3 lines, which fills each equal
   .hero-banner-features li column edge to edge - the horizontal spacing
   there comes for free from justify-content: space-between. These labels
   are short one-liners (three or four per tool page vs. six on the
   homepage), so the same equal-width columns would leave each one
   left-aligned with a lot of dead space after it. Size each item to its
   own content instead, so space-between distributes gaps between the
   actual icon+text groups the same way it visually reads on the homepage. */
ul.tool-hero-banner-features li {
    flex: 0 0 auto;
}

/* ==========================================================================
   Hero banner (home page, full-width image with text overlay)
   ========================================================================== */

.hero-banner {
    position: relative;
    margin: 2rem auto 0;
    border-radius: var(--bs-border-radius-lg);
    overflow: hidden;
    border: 1px solid var(--border-subtle);
    /* Matches the source render's own proportions (1916x821) so the whole
       scene shows uncropped, exactly as composed - the render already has
       a near-black band above the mannequin's head and a darker workbench
       band at the bottom, which is where the text below is placed to sit
       on, rather than over the busy middle of the image. */
    aspect-ratio: 1916 / 821;
}

.hero-banner-image {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

.hero-banner-scrim {
    position: absolute;
    inset: 0;
    /* Light touch only - the render's own top/bottom bands already do
       most of the contrast work, this just reinforces them a bit and
       stays fully clear over the middle so the illustration reads at
       full brightness there, same as the reference layout. */
    background: linear-gradient(
        180deg,
        rgba(10, 10, 12, .55) 0%,
        rgba(10, 10, 12, .18) 22%,
        rgba(10, 10, 12, 0) 34%,
        rgba(10, 10, 12, 0) 66%,
        rgba(10, 10, 12, .2) 80%,
        rgba(10, 10, 12, .62) 100%
    );
}

.hero-banner-content {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: center;
    padding: clamp(0.5rem, 1.5vw, 1.25rem) clamp(1rem, 4vw, 3rem) clamp(0.25rem, 0.75vw, 0.5rem);
}

.hero-banner-text {
    text-align: center;
}

.hero-banner-title {
    font-size: clamp(1.15rem, 3.6vw, 2.75rem);
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--text-primary);
    margin-bottom: 0.2em;
    text-shadow: 0 2px 16px rgba(0, 0, 0, .7);
}

.hero-banner-dot {
    color: var(--accent-400);
    margin: 0 0.2em;
}

.hero-banner-subtitle {
    max-width: 46rem;
    margin: 0 auto;
    color: rgba(242, 242, 240, .9);
    font-size: clamp(0.6rem, 1.35vw, 1.05rem);
    line-height: 1.3;
    text-shadow: 0 1px 10px rgba(0, 0, 0, .7);
}

.hero-banner-features {
    list-style: none;
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    width: 100%;
    margin: 0;
    padding: 0;
    gap: clamp(0.25rem, 1.5vw, 1rem);
}

.hero-banner-features li {
    display: flex;
    align-items: center;
    gap: 0.5em;
    flex: 1 1 0;
    min-width: 0;
    text-align: left;
}

.hero-banner-features span {
    display: block;
    font-size: clamp(0.5rem, 1vw, 0.8rem);
    font-weight: 600;
    line-height: 1.25;
    color: rgba(242, 242, 240, .92);
    text-shadow: 0 1px 8px rgba(0, 0, 0, .7);
}

.hero-banner-features i {
    flex-shrink: 0;
    color: var(--accent-400);
    font-size: clamp(0.85rem, 1.8vw, 1.4rem);
    text-shadow: 0 1px 8px rgba(0, 0, 0, .7);
}

@media (max-width: 575.98px) {
    /* The locked aspect-ratio leaves ~170px of height at phone width, not
       enough room for the subtitle and six badges to stay legible - drop
       both and keep just the headline as the image's caption. The
       full-text hero right below repeats this same copy accessibly. */
    .hero-banner-subtitle,
    .hero-banner-features {
        display: none;
    }
}

/* ==========================================================================
   Step indicator (wizard pages)
   ========================================================================== */

.step-indicator {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-bottom: 2.5rem;
    padding: 0;
    list-style: none;
}

.step-indicator li {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.step-indicator .step-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    border: 1px solid var(--border-strong);
    color: var(--text-muted);
    font-size: 0.8rem;
    font-weight: 600;
    background: var(--surface-1);
}

.step-indicator .step-label {
    font-size: 0.85rem;
    color: var(--text-muted);
    margin-right: 0.5rem;
}

.step-indicator .step-connector {
    width: 1.5rem;
    height: 1px;
    background: var(--border-subtle);
    margin-inline: 0.25rem;
}

.step-indicator li.is-complete .step-dot {
    background: var(--accent-500);
    border-color: var(--accent-500);
    color: #14100a;
}

.step-indicator li.is-current .step-dot {
    border-color: var(--accent-500);
    color: var(--accent-400);
}

.step-indicator li.is-current .step-label {
    color: var(--text-primary);
    font-weight: 600;
}

/* ==========================================================================
   Forms
   ========================================================================== */

.form-control,
.form-select {
    background-color: var(--surface-1);
    border-color: var(--border-strong);
    color: var(--text-primary);
    padding: 0.55rem 0.85rem;
}

.form-control:focus,
.form-select:focus {
    background-color: var(--surface-1);
    color: var(--text-primary);
    border-color: var(--accent-500);
    box-shadow: 0 0 0 0.2rem rgba(var(--accent-rgb), 0.25);
}

.form-check-input {
    background-color: var(--surface-1);
    border-color: var(--border-strong);
}

.form-check-input:checked {
    background-color: var(--accent-500);
    border-color: var(--accent-500);
}

.form-label {
    font-weight: 500;
    color: var(--text-muted);
    font-size: 0.9rem;
}

/* ==========================================================================
   Dropzone (upload page)
   ========================================================================== */

.dropzone {
    position: relative;
    border: 2px dashed var(--border-strong);
    border-radius: var(--bs-border-radius-lg);
    padding: 3rem 1.5rem;
    text-align: center;
    cursor: pointer;
    background: var(--surface-1);
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.dropzone:hover {
    border-color: var(--accent-600);
}

.dropzone.is-dragover {
    border-color: var(--accent-500);
    background: var(--bs-primary-bg-subtle);
}

.dropzone-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.dropzone-icon {
    font-size: 2.25rem;
    line-height: 1;
    margin-bottom: 0.75rem;
}

.dropzone-browse {
    color: var(--accent-400);
    text-decoration: underline;
}

.dropzone-preview {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
}

.dropzone-thumb {
    width: 3.5rem;
    height: 3.5rem;
    object-fit: cover;
    border-radius: var(--bs-border-radius);
    border: 1px solid var(--border-subtle);
    background: var(--surface-2);
}

/* ==========================================================================
   Footer
   ========================================================================== */

.footer-app {
    border-top: 1px solid var(--border-subtle);
    padding: 2rem 0;
    color: var(--text-muted);
    font-size: 0.875rem;
}

.footer-app a {
    color: var(--text-muted);
}

.footer-app a:hover {
    color: var(--text-primary);
}

.footer-app__links {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 1rem;
}

/* A .btn (it opens the feedback modal), but sized like the links beside it
   - Bootstrap's 1rem/underline made it read as a different, bigger thing.
   The accent color alone marks it as the footer's one action. */
.footer-app .footer-app__feedback {
    padding: 0;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    color: var(--accent-400);
    text-decoration: none;
}

.footer-app .footer-app__feedback:hover {
    color: var(--accent-400);
    text-decoration: underline;
}

/* Phones: tagline above, then the action on its own row and the four page
   links in a 2x2 grid - a wrapping row broke raggedly (one link stranded
   per line), and the old unwrapped row ran off the screen. The vertical
   padding gives each link a ~40px tap target. */
@media (max-width: 575.98px) {
    .footer-app .container {
        flex-direction: column;
        gap: 1rem !important;
    }

    .footer-app__links {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 0 1rem;
    }

    .footer-app__links > * {
        padding: 0.5rem 0;
        justify-self: start;
    }

    .footer-app .footer-app__feedback {
        grid-column: 1 / -1;
        padding: 0.5rem 0;
    }
}

/* ==========================================================================
   Misc
   ========================================================================== */

.text-muted-app {
    color: var(--text-muted) !important;
}

.mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums;
}

.table {
    --bs-table-bg: transparent;
    --bs-table-color: var(--text-primary);
    --bs-table-border-color: var(--border-subtle);
}

/* Strip the default disclosure triangle so <summary> reads as a plain
   icon-button trigger for the inline rename form on my_projects. */
.rename-toggle {
    display: inline-block;
    cursor: pointer;
    list-style: none;
    color: var(--text-muted);
}

.rename-toggle:hover {
    color: var(--accent-400);
}

.rename-toggle::-webkit-details-marker {
    display: none;
}

.calibration-tips summary {
    cursor: pointer;
    list-style: none;
}

.calibration-tips summary:hover {
    color: var(--text-primary);
}

.calibration-tips summary::-webkit-details-marker {
    display: none;
}

.calibration-tips ul {
    padding-left: 1.25rem;
}

.project-thumbnail {
    width: 48px;
    height: 48px;
    object-fit: cover;
    border-radius: 6px;
    background-color: var(--border-subtle);
}

.project-thumbnail-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
    color: var(--text-muted);
}

.project-thumbnail-placeholder img {
    width: 1.75rem;
    height: 1.75rem;
}

/* Small per-row indicator on my_projects distinguishing which CosFaro tool
   a project belongs to (Poster Maker vs Prop Scaler) - deliberately just
   an icon, not a text label, to keep the row compact; the tooltip carries
   the actual name. */
.tool-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 0.5rem;
    background: var(--bs-primary-bg-subtle);
    color: var(--accent-400);
    font-size: 0.9rem;
    flex-shrink: 0;
}

.tool-badge img {
    width: 1.5rem;
    height: 1.5rem;
}

/* Icon-only row actions (View/Continue/Duplicate/Delete) on my_projects -
   same muted-until-hover treatment as .rename-toggle/.nudge-btn, so every
   icon-button across the app behaves consistently. .text-danger on the
   delete action overrides the hover color too, via the more specific
   selector below, so it stays reachable as "danger" red rather than
   flipping to the accent color like the others. */
.icon-action {
    color: var(--text-muted);
    font-size: 1.1rem;
    line-height: 1;
    text-decoration: none;
}

.icon-action:hover {
    color: var(--accent-400);
}

.icon-action.text-danger:hover {
    color: var(--bs-danger) !important;
}

/* Bootstrap's modal ships light-theme defaults; remapped onto this
   site's own tokens. Unscoped (not tied to one modal id) - used by
   every "resume a local project" landing-page list's delete-confirm
   modal (Pattern Editor/Poster Maker/Unfolder/Prop Scaler landing
   pages), and available for any future modal without needing its own
   copy of this override. */
.modal-content {
    background: var(--surface-1);
    border: 1px solid var(--border-subtle);
    color: var(--text-primary);
}
.modal-header,
.modal-footer {
    border-color: var(--border-subtle);
}
.btn-close {
    filter: invert(1) grayscale(1) brightness(1.5);
}

/* Settings-row layout for modal-based preference panels (Unfolder's own
   Preferences modal today - unscoped so any future settings modal can
   reuse it without its own copy). Replaces the sidebar-era pattern of
   cramming a whole section's controls into one flex-wrap row, which
   reflows unpredictably once a conditional field (a material preset) or a
   longer translated label changes how much fits per line - one row per
   setting reads the same regardless. */
.settings-section + .settings-section {
    margin-top: 1.25rem;
    padding-top: 1.1rem;
    border-top: 1px solid var(--border-subtle);
}

.settings-section-header {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    margin-bottom: 0.15rem;
}

.settings-section-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: var(--bs-border-radius-sm);
    background: rgba(var(--accent-rgb), 0.14);
    color: var(--accent-400);
    font-size: 0.8rem;
    flex-shrink: 0;
}

.settings-section-title {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-primary);
}

.settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.4rem 1rem;
    padding: 0.6rem 0 0.6rem 2.15rem;
}

.settings-row + .settings-row {
    border-top: 1px solid var(--border-subtle);
}

/* A row that only exists beneath its parent setting (a material preset/
   thickness field shown only for the matching mode) - sits closer to the
   row above with no divider of its own, so it reads as refining that
   setting rather than as a new, equally-weighted one. Declared after the
   adjacent-sibling rule above so it wins at equal specificity. */
.settings-row.settings-row-sub {
    padding-top: 0.4rem;
    padding-left: 3.15rem;
    border-top: none;
}

/* Each row's label is a real <label for="...">, not just adjacent text -
   clicking it focuses (or, for the export-tabs checkbox, toggles) its
   control, the same affordance a native form gives for free. */
.settings-row-label {
    font-size: 0.8rem;
    color: var(--text-primary);
    flex: 1 1 auto;
    min-width: 8rem;
    cursor: pointer;
}

.settings-row-control {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex: 0 0 auto;
}

/* ==========================================================================
   Site access (SiteAccess / admin/site_access.html.twig)
   Public side: the closed sign-up/login panel, the maintenance banner and
   the admins-only reminder strip. Admin side: one sheet of three rows
   (status dot, title, Open/Closed switch, message) next to a live preview
   of what visitors see - the preview is the page's one prominent element,
   the sheet stays quiet. Amber marks "something is closed or announced";
   the switches themselves stay neutral so the dot carries the state.
   ========================================================================== */

.admin-access-strip {
    background: var(--surface-1);
    border-bottom: 1px solid var(--border-subtle);
    font-size: 0.85rem;
    padding: 0.45rem 0;
}

.admin-access-strip__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 0.65rem;
}

.site-notice {
    background: var(--surface-1);
    border-top: 2px solid var(--accent-500);
    border-bottom: 1px solid var(--border-subtle);
    padding: 0.7rem 0;
}

.site-notice--live {
    background: rgba(var(--accent-rgb), 0.12);
}

.site-notice__inner {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
}

.site-notice__icon {
    color: var(--accent-400);
    font-size: 1.05rem;
    line-height: 1.4;
}

.site-notice__text {
    flex: 1;
    min-width: 0;
    font-size: 0.9rem;
    line-height: 1.5;
    max-width: 75ch;
}

.site-notice__title {
    margin: 0;
    font-weight: 600;
    color: var(--text-primary);
}

.site-notice__message {
    margin: 0;
    overflow-wrap: anywhere;
}

.site-notice__message a {
    color: var(--accent-400);
    text-decoration: underline;
    text-underline-offset: 0.15em;
}

.site-notice__message a:hover {
    color: var(--text-primary);
}

/* The admin-written announcement: same layout as the maintenance notice,
   told apart by colour and icon. */
.site-notice--announcement {
    border-top-color: var(--chalk-500);
}

.site-notice--announcement .site-notice__icon {
    color: var(--chalk-400);
}

.site-notice__text time {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.site-notice__dismiss {
    flex-shrink: 0;
    margin-left: auto;
    font-size: 0.7rem;
    padding: 0.45rem;
}

.access-closed__mark {
    display: inline-grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    margin-bottom: 1rem;
    border: 1px solid rgba(var(--accent-rgb), 0.45);
    border-radius: 50%;
    color: var(--accent-400);
    font-size: 1.15rem;
}

.access-closed__message {
    white-space: pre-line;
    margin-bottom: 0.75rem;
}

.access-closed__aside {
    color: var(--text-muted);
    font-size: 0.875rem;
    margin-bottom: 1.25rem;
}

.access-closed__admin {
    margin-top: 1.5rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border-subtle);
}

.access-closed__admin summary,
.access-closed__admin-summary {
    color: var(--text-muted);
    font-size: 0.875rem;
    cursor: pointer;
}

.access-closed__admin summary:hover {
    color: var(--text-primary);
}

.sa-closed-note {
    color: var(--accent-400);
}

/* Registration: the short summary of what the terms checkbox agrees to. */
.register-terms {
    margin: 0 0 0.75rem;
    padding: 0.85rem 1rem 0.85rem 2rem;
    border: 1px solid var(--border-subtle);
    border-radius: var(--bs-border-radius);
    background: var(--surface-2);
    color: var(--text-muted);
    font-size: 0.85rem;
}

.register-terms li + li {
    margin-top: 0.35rem;
}

/* Beta application form honeypot (BetaApplicationFormType) - off-screen
   for people, still a normal field for bots. */
.beta-honeypot {
    position: absolute;
    left: -10000px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}
