/* =============================================================================
   Peepful design tokens — "The Field Notes" (see DESIGN.md)
   Warm ink on paper. One rationed clay accent. Flat by default.
   ============================================================================= */
:root {
    /* Shoelace primary ramp, remapped to Clay (the single accent) */
    --sl-color-primary-50: #f8efe9;
    --sl-color-primary-100: #f1ddd2;
    --sl-color-primary-200: #e8c5b5;
    --sl-color-primary-300: #d9a48c;
    --sl-color-primary-400: #c57a5e;
    --sl-color-primary-500: #b1543a;
    --sl-color-primary-600: #9e4a33;
    --sl-color-primary-700: #843a29;
    --sl-color-primary-800: #6b3022;
    --sl-color-primary-900: #54271c;
    --sl-color-primary-950: #3a1a13;

    /* Warm neutral surfaces for Shoelace components (panels, inputs, light fills) */
    --sl-color-neutral-0: #fcf9f3;
    --sl-color-neutral-50: #f6f2e9;
    --sl-color-neutral-100: #efe9dd;
    --sl-panel-background-color: #fcf9f3;
    --sl-input-background-color: #fcf9f3;

    /* App palette — warm ink on paper */
    --primary-color: #b1543a;    /* Clay — primary actions, links, focus, active */
    --primary-hover: #97462f;    /* Clay Deep — pressed/hover on clay */
    --clay-tint: #f1ddd2;        /* Wash behind avatars / clay chips */
    --secondary-color: #6f675b;  /* Taupe */
    --secondary-hover: #565047;
    --success-color: #5e7a4f;    /* Moss */
    --error-color: #9f4030;      /* Brick */
    --warning-color: #bd7e36;    /* Ochre */
    --text-color: #25221c;       /* Ink */
    --text-muted: #6f675b;       /* Taupe */
    --bg-color: #f6f2e9;         /* Paper — the page field */
    --card-bg: #fcf9f3;          /* Paper Surface — records, header, footer */
    --paper-sunken: #efe9dd;     /* Hover fills, inset wells */
    --border-color: #e6ddcf;     /* Stone — the 1px structural border */

    /* Elevation — flat at rest; warm lift only on hover, clay ring on focus */
    --hover-lift: 0 1px 2px rgba(40, 33, 24, 0.05), 0 6px 20px rgba(40, 33, 24, 0.07);
    --focus-ring: 0 0 0 3px rgba(177, 84, 58, 0.20);

    /* Typography — one voice */
    --sl-font-sans: 'IBM Plex Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --sl-font-size-medium: 1rem;

    /* Radius — crisp, lightly rounded */
    --sl-border-radius-small: 3px;
    --sl-border-radius-medium: 6px;
    --sl-border-radius-large: 8px;
}

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

/* Prevent the flash of undefined custom elements (FOUCE).
   The nav and much of the UI are Shoelace web components registered by JS via
   the autoloader. Until they're defined, the browser paints them as raw,
   unstyled markup. Hide undefined custom elements until Shoelace upgrades them;
   visibility (not display) keeps their layout space so nothing jumps. */
:not(:defined) {
    visibility: hidden;
}

/* An undefined <sl-icon> is an empty inline box with no width, so text sitting
   next to one slides sideways the moment it upgrades. Reserve the 1em box the
   defined icon will occupy. */
sl-icon:not(:defined) {
    display: inline-block;
    width: 1em;
    height: 1em;
}

body {
    font-family: var(--sl-font-sans);
    line-height: 1.6;
    color: var(--text-color);
    background-color: var(--bg-color);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 1rem;
    width: 100%;
}

/* Header */
.app-header {
    /* Settled height of a medium Shoelace control (--sl-input-height-medium).
       The header row reserves it so the nav can't change the header's height as
       it upgrades; see the FOUCE note below. */
    --nav-control-height: 2.5rem;

    background-color: var(--card-bg);
    border-bottom: 1px solid var(--border-color);
    padding: 0.75rem 0;
    position: sticky;
    top: 0;
    z-index: 100;
}

/* Touch input: 44px minimum target, so the row grows to match. */
@media (pointer: coarse) {
    .app-header {
        --nav-control-height: 2.75rem;
    }
}

.header-inner {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    min-height: var(--nav-control-height);
}

.brand {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--text-color);
    text-decoration: none;
}

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

.brand-icon {
    font-size: 1.5rem;
    color: var(--primary-color);
}

.app-nav {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Before the autoloader upgrades them, these controls are raw inline text that
   wraps into a tall stack — the header used to load at 259px and snap to 65px.
   The global :not(:defined) rule hides that text but keeps its layout box, so
   take the un-upgraded controls out of flow entirely. With .header-inner
   holding the row open, first paint and settled paint are the same geometry:
   the nav fades in where it already had room, instead of resizing the page. */
.app-nav > :not(:defined) {
    display: none;
}

.app-nav sl-button::part(base) {
    font-weight: 500;
    min-height: var(--nav-control-height);
}

/* A username is arbitrary-length text in a fixed-width row; cap it so a long
   one truncates instead of pushing the nav off-screen. */
.nav-account::part(label) {
    max-width: 14ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The menu repeats the username only when the trigger has stopped showing it. */
.nav-account-name {
    display: none;
}

/* Current section: bolder, full clay, with a 2px clay underline so "you are
   here" reads clearly (the text buttons are already clay-ish) — DESIGN.md active nav. */
.app-nav sl-button.is-active::part(base) {
    color: var(--primary-color);
    font-weight: 600;
    box-shadow: inset 0 -2px 0 var(--primary-color);
}

.app-nav sl-dropdown sl-menu-item a,
.app-nav sl-dropdown sl-menu-item .logout-button {
    color: inherit;
    text-decoration: none;
    display: block;
    width: 100%;
}

/* The full-width <a>/<button> in the label slot sits flush against the prefix
   icon, so give the icon some breathing room before the text. */
.app-nav sl-dropdown sl-menu-item sl-icon[slot="prefix"] {
    margin-inline-end: 0.625rem;
}

/* Logout is a POST form (Django requires POST); make the button read as a menu link */
.app-nav sl-dropdown sl-menu-item .logout-form {
    margin: 0;
}

.app-nav sl-dropdown sl-menu-item .logout-button {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

/* Compact nav. Below this the wordmark plus three labelled controls stop
   fitting one row, and the nav used to wrap into a three-row block 153px tall.
   Wrapping is the wrong answer here: the labels are what make the sections
   scannable, so the decoration goes instead — link icons off, and the account
   control becomes the person glyph alone. */
@media (max-width: 640px) {
    .app-nav {
        gap: 0.125rem;
        /* Flex items floor at their content width unless told otherwise; without
           this the nav can't shrink and the safety valve below never engages. */
        min-width: 0;
    }

    .app-nav sl-button::part(base) {
        padding-inline: 0.625rem;
    }

    .nav-link::part(prefix) {
        display: none;
    }

    /* Safety valve, not a layout: the labels fit at every size handled below,
       but a wide fallback font mid-load, or a viewport narrower than 320px,
       would otherwise push the nav off the page. Let them truncate instead. */
    .nav-link {
        min-width: 0;
    }

    .nav-link::part(label) {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .nav-account::part(caret) {
        display: none;
    }

    .nav-account::part(base) {
        min-width: var(--nav-control-height);
        justify-content: center;
    }

    /* Clipped, not hidden: the username stays the trigger's accessible name. */
    .nav-account::part(label) {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .nav-account-name {
        display: block;
    }
}

/* The wordmark and the compact nav together need ~432px of row, which no phone
   in portrait has. The wordmark is the least load-bearing thing there — the
   glyph still reads as home, and the section labels are what users aim at — so
   below 480px it goes. Clipped, not removed: the link keeps its accessible name. */
@media (max-width: 480px) {
    .brand-wordmark {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
}

/* Smallest phones, and the 320px reflow floor of WCAG 1.4.10 — which is also
   where someone at 200% zoom lands. Shrinking the type there would undo the
   zoom they asked for, so the long label gives way to the product's own short
   name for it instead, at full size. */
.nav-label-tight {
    display: none;
}

@media (max-width: 380px) {
    .nav-label {
        display: none;
    }

    .nav-label-tight {
        display: inline;
    }
}

/* Main content */
.main-content {
    flex: 1;
    padding: 2rem 0;
}

/* Messages */
.messages {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 1.5rem;
}

.messages sl-alert {
    --sl-panel-background-color: var(--card-bg);
}

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

.page-header h1 {
    margin: 0;
    font-size: 1.75rem;
}

/* Hero section */
.hero {
    text-align: center;
    padding: 4rem 0;
}

.hero h1 {
    font-size: 2.5rem;
    margin-bottom: 1rem;
    color: var(--text-color);
}

.hero p {
    font-size: 1.25rem;
    color: var(--text-muted);
    margin-bottom: 2rem;
}

.cta {
    display: flex;
    gap: 1rem;
    justify-content: center;
    flex-wrap: wrap;
}

/* Cards */
.sl-card, .card {
    background-color: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: var(--sl-border-radius-large);
    padding: 1.5rem;
    transition: box-shadow 0.2s, transform 0.2s;
}

.sl-card:hover, .card:hover {
    box-shadow: var(--hover-lift);
}

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

.card p {
    color: var(--text-muted);
    margin-bottom: 1rem;
}

/* Tag badges */
.tag-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.25rem 0.75rem;
    border-radius: 9999px;
    font-size: 0.85rem;
    font-weight: 500;
    border: 1px solid;
    white-space: nowrap;
}

.tag-badge-sm {
    padding: 0.125rem 0.5rem;
    font-size: 0.75rem;
}

/* Forms */
.form-page {
    max-width: 600px;
    margin: 0 auto;
}

.form-page h1 {
    margin-bottom: 1.5rem;
}

.form-group {
    margin-bottom: 1.25rem;
}

.form-group label {
    display: block;
    margin-bottom: 0.5rem;
    font-weight: 500;
    color: var(--text-color);
}

.form-actions {
    display: flex;
    gap: 0.75rem;
    margin-top: 1.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--border-color);
}

/* Shoelace input styling */
sl-input::part(base),
sl-textarea::part(base),
sl-select::part(combobox) {
    border-color: var(--border-color);
}

sl-input::part(base):focus-within,
sl-textarea::part(base):focus-within,
sl-select::part(combobox):focus-within {
    border-color: var(--primary-color);
    box-shadow: var(--focus-ring);
}

/* Visible keyboard focus for native interactive elements. Shoelace components
   (sl-button, sl-input, …) carry their own focus ring; this covers the native
   links and buttons they don't — person names, the +Tag/tag toggles, nav and
   menu links — which otherwise focus invisibly (a WCAG 2.4.7 failure). */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
}

/* Auth forms */
.auth-form {
    max-width: 400px;
    margin: 0 auto;
    background-color: var(--card-bg);
    padding: 2rem;
    border-radius: var(--sl-border-radius-large);
    border: 1px solid var(--border-color);
}

.auth-form h1 {
    margin-bottom: 1.5rem;
    text-align: center;
}

.auth-form p {
    margin-bottom: 1rem;
}

.auth-form label {
    display: block;
    margin-bottom: 0.25rem;
    font-weight: 500;
}

.auth-form input[type="text"],
.auth-form input[type="email"],
.auth-form input[type="password"],
.auth-form textarea,
.auth-form select {
    width: 100%;
    padding: 0.75rem;
    border: 1px solid var(--border-color);
    border-radius: 0.375rem;
    font-size: 1rem;
    margin-bottom: 1rem;
    transition: border-color 0.2s, box-shadow 0.2s;
}

.auth-form input:focus,
.auth-form textarea:focus,
.auth-form select:focus {
    outline: none;
    border-color: var(--primary-color);
    box-shadow: var(--focus-ring);
}

.auth-form button {
    width: 100%;
    margin-top: 0.5rem;
}

.auth-link {
    text-align: center;
    margin-top: 1.5rem;
    color: var(--text-muted);
}

.auth-link a {
    color: var(--primary-color);
    text-decoration: none;
    font-weight: 500;
}

.auth-link a:hover {
    text-decoration: underline;
}

/* Legacy button styles (for Django form rendering) */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.625rem 1.25rem;
    border-radius: 0.375rem;
    font-weight: 500;
    font-size: 0.95rem;
    text-decoration: none;
    cursor: pointer;
    border: 1px solid transparent;
    transition: all 0.2s;
    white-space: nowrap;
}

.btn-primary {
    background-color: var(--primary-color);
    color: white;
    border-color: var(--primary-color);
}

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

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

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

.btn-danger {
    background-color: var(--error-color);
    color: white;
    border-color: var(--error-color);
}

.btn-danger:hover {
    background-color: #8a3727;
    border-color: #8a3727;
}

.btn-sm {
    padding: 0.375rem 0.75rem;
    font-size: 0.85rem;
}

/* Profile page */
.profile h1 {
    margin-bottom: 1.5rem;
}

.profile h2 {
    margin-top: 2rem;
    margin-bottom: 1rem;
    font-size: 1.25rem;
}

.profile-info {
    background-color: var(--card-bg);
    padding: 1.5rem;
    border-radius: var(--sl-border-radius-large);
    border: 1px solid var(--border-color);
    margin-bottom: 1.5rem;
}

.profile-info p {
    margin-bottom: 0.5rem;
    display: flex;
    gap: 0.5rem;
}

.profile-info strong {
    min-width: 100px;
    color: var(--text-muted);
    font-weight: 500;
}

.profile form {
    background-color: var(--card-bg);
    padding: 1.5rem;
    border-radius: var(--sl-border-radius-large);
    border: 1px solid var(--border-color);
}

.profile-actions {
    margin-top: 2rem;
}

/* Footer */
.app-footer {
    background-color: var(--card-bg);
    border-top: 1px solid var(--border-color);
    padding: 1.5rem 0;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.9rem;
}

/* Form errors */
.errorlist {
    list-style: none;
    color: var(--error-color);
    font-size: 0.875rem;
    margin-bottom: 0.5rem;
}

.helptext {
    font-size: 0.875rem;
    color: var(--text-muted);
    margin-top: -0.75rem;
    margin-bottom: 1rem;
}

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

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

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

/* Direct child only: the large decorative icon. A descendant selector here
   also matches the small prefix icon inside the empty state's <sl-button>,
   blowing it up to 3rem and pushing it off-center. */
.empty-state > sl-icon {
    font-size: 3rem;
    margin-bottom: 1rem;
    opacity: 0.5;
}

.empty-state p {
    margin-bottom: 1rem;
}

/* Checkbox list for tags */
.checkbox-list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.checkbox-item {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    cursor: pointer;
}

.checkbox-item input {
    margin-right: 0.25rem;
}

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

.search-bar sl-input {
    width: 100%;
}

/* Grid layouts */
.grid-auto {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 1.5rem;
}

/* Status badges using Shoelace badges — earthen, never neon */
sl-badge[variant="success"] {
    --sl-color-success-600: var(--success-color);
}

sl-badge[variant="warning"] {
    --sl-color-warning-600: var(--warning-color);
}

sl-badge[variant="danger"] {
    --sl-color-danger-600: var(--error-color);
}

/* Skeleton loading states */
.skeleton {
    background: linear-gradient(90deg, var(--border-color) 25%, #f3eee4 50%, var(--border-color) 75%);
    background-size: 200% 100%;
    animation: skeleton-loading 1.5s infinite;
    border-radius: 0.25rem;
}

@keyframes skeleton-loading {
    0% {
        background-position: 200% 0;
    }
    100% {
        background-position: -200% 0;
    }
}

/* Metadata / extracted facts (shared `metadata_facts` inclusion tag) */
.metadata-facts {
    margin: 0;
}

.metadata-facts dt {
    margin: 0;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.metadata-facts dd {
    margin: 0;
    font-weight: 500;
    color: var(--text-color);
}

.metadata-facts--grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 1rem;
}

.metadata-facts--grid .metadata-fact {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.metadata-facts--pills {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.metadata-facts--pills .metadata-fact {
    display: inline-flex;
    align-items: baseline;
    gap: 0.4rem;
    padding: 0.2rem 0.6rem;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background: var(--bg-color);
    font-size: 0.82rem;
}

.metadata-facts--pills dt {
    font-size: 0.64rem;
}

/* Import status (polled fragment — styles here, not inline, to avoid
   re-injecting a <style> block on every 2s poll) */
.import-status {
    padding: 0 0 1.25rem 0;
    border-bottom: 1px solid var(--border-color);
}

.import-status-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.import-status-state {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.import-status-spinner {
    font-size: 1.1rem;
    --indicator-color: var(--primary-color);
}

.import-status-count {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    color: var(--text-muted);
    font-size: 0.9rem;
    font-variant-numeric: tabular-nums;
}

.import-status-progress {
    margin-bottom: 1rem;
    --height: 6px;
    --indicator-color: var(--primary-color);
    --track-color: var(--paper-sunken);
}

.import-status-description,
.import-status-note {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    color: var(--text-muted);
}

.import-status-description sl-icon {
    color: var(--primary-color);
}

.import-status-note {
    margin-top: 0.75rem;
    font-size: 0.9rem;
}

/* Responsive utilities */
@media (max-width: 768px) {
    .page-header {
        flex-direction: column;
        align-items: flex-start;
    }

    .page-header h1 {
        font-size: 1.5rem;
    }

    .hero h1 {
        font-size: 2rem;
    }

    .hero p {
        font-size: 1.1rem;
    }
}

/* Honor reduced-motion: neutralize non-essential animation and transitions */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}
