/* ==========================================================================
   Base CSS - Global styles for Reflekt application
   ========================================================================== */

/* CSS Custom Properties */
:root {
    /* Brand palette — reconciled to the indigo the app actually renders in.
       (History: the UI shipped indigo #6366f1/#8b5cf6 while CLAUDE.md still
       documented #4f46e5/#7c3aed, and 280 Bootstrap utilities rendered
       Bootstrap's own blue on top of that. One token drives all of it now.) */
    /* Slate Blue. Desaturated navy - reads closer to charcoal than to blue,
       so the colour never competes with the writing. Every ratio below is
       WCAG AA or better against white; see mds/DESIGN_AUDIT.md. */
    --primary-color: #3A5470;      /* Slate 500 - the brand          (7.83:1 on white) */
    --primary-dark: #2E4359;       /* Slate 600 - hover             (10.18:1) */
    --primary-darker: #223243;     /* Slate 700 - pressed           (13.08:1) */
    --secondary-color: #5A7FA6;    /* Steel 400 - gradient partner   (4.18:1) */
    --secondary-dark: #46648A;     /* Steel 500 - hover on secondary */

    /* Subtle brand tints, for backgrounds and quiet borders. */
    --primary-subtle: #E3E8EE;         /* tinted surface */
    --primary-border-subtle: #BFCAD8;  /* quiet border */
    --primary-emphasis: #1A2733;       /* text on a tint (12.33:1 on subtle) */

    /* Channel triples. Bootstrap builds colours as rgba(var(--x-rgb), opacity),
       and CSS cannot decompose a hex into channels, so these must be kept in
       step with the hex values above by hand. */
    --primary-rgb: 58, 84, 112;
    --primary-dark-rgb: 46, 67, 89;
    --secondary-rgb: 90, 127, 166;

    /* The one brand gradient. Auth, pricing, the blog header and the yearly
       dashboard each shipped their own #667eea -> #764ba2 version, which was
       off-brand in every one of them. */
    --gradient-brand: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);

    /* Card geometry. Two radii, both documented in CLAUDE.md: the standard
       card surface, and the compact one used for dense rows like .entry-card.
       Anything smaller (icons, pills, chips, buttons) sets its own literal -
       those are controls, not cards. */
    --radius-card: 16px;
    --radius-card-sm: 12px;
    --radius-control: 10px;        /* buttons, inputs, selects */
    --radius-control-sm: 8px;      /* the -sm variants */
    --radius-pill: 999px;          /* badges and pills */

    /* Card depth. One rest shadow and one hover shadow for the whole site -
       there were six different treatments before. Values are the ones
       components/cards.css already used, so adopting the system conforms the
       outliers rather than moving the standard. */
    --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.08);
    --shadow-card-hover: 0 4px 12px rgba(0, 0, 0, 0.12);

    /* Card density. Four different paddings were in use. */
    --pad-card: 1.25rem;
    --pad-card-header: 1rem 1.25rem;

    /* ------------------------------------------------------------------
       Status palette. These were 151 raw hexes scattered across a dozen
       files with no single definition - which is how "warning" quietly came
       to mean two different things. One definition each, all AA on their own
       tint (6.3:1 or better).
       ------------------------------------------------------------------ */
    --status-success-bg: #dcfce7;  --status-success-ink: #166534;  --status-success-border: #bbf7d0;
    --status-danger-bg:  #fee2e2;  --status-danger-ink:  #991b1b;  --status-danger-border:  #fecaca;
    --status-warning-bg: #fef3c7;  --status-warning-ink: #92400e;  --status-warning-border: #fde68a;
    --status-info-bg:    #dbeafe;  --status-info-ink:    #1e40af;  --status-info-border:    #bfdbfe;

    /* Dormant / discontinued. Added because "Abandoned" was borrowing the
       warning tint, and an abandoned book is not a warning. */
    --status-muted-bg:   #EEF1F4;  --status-muted-ink:   #47535F;  --status-muted-border:   #D6DDE4;

    /* Premium / upgrade. A solid accent, deliberately separate from the pale
       warning tint above - the two must never be confused for each other. */
    --accent-premium: #E8B84B;
    --accent-premium-hover: #D9A733;
    --accent-premium-ink: #3F2D08;

    /* Type families — system sans for UI/body,
       mono for dates / counts / labels (echoes the Consolas editor). */
    --font-sans:  ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-mono:  ui-monospace, "SF Mono", "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace;

    /* Display face for headings. Same Georgia as the body copy: one editorial
       voice across headings and prose, and it is a system face everywhere that
       matters, so it costs nothing to load. */
    --font-display: Georgia, "Times New Roman", Times, serif;

    /* Long-form reading serif for article body copy. Georgia is a system
       face on macOS/Windows/iOS so it costs nothing to use; Android has no
       Georgia and falls through to its own serif. */
    --font-serif: Georgia, "Times New Roman", Times, serif;

    /* Type scale (px in comments) */
    --fs-xs:   0.75rem;   /* 12 */
    --fs-sm:   0.875rem;  /* 14 */
    --fs-base: 1rem;      /* 16 */
    --fs-md:   1.125rem;  /* 18 */
    --fs-lg:   1.375rem;  /* 22 */
    --fs-xl:   1.75rem;   /* 28 */
    --fs-2xl:  2.25rem;   /* 36 */
    --fs-3xl:  3rem;      /* 48 */

    /* Line heights */
    --lh-tight:  1.15;
    --lh-snug:   1.35;
    --lh-normal: 1.6;
}

/* ==========================================================================
   Accessibility baseline (global)
   ========================================================================== */

/* Visible keyboard focus, app-wide. `:focus-visible` only matches keyboard /
   programmatic focus, so mouse users never see it. The `:not(:focus-visible)`
   rule removes the default UA outline on mouse/touch focus without killing the
   keyboard indicator — the correct modern replacement for `outline: none`. */
:focus:not(:focus-visible) {
    outline: none;
}
:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
    border-radius: 3px;
}

/* Respect users who ask their OS for reduced motion. */
@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;
    }
}

/* ==========================================================================
   Typography — "Ledger of Days" type system
   ========================================================================== */

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: var(--font-display);
}

/* Georgia ships Regular and Bold only - no semibold. A `600` here would
   silently resolve to 700 anyway, so declare the weight that actually
   renders. Bold also does real work now that headings and body share a
   family: at the small end an h4 sits barely above body size, and weight is
   what keeps the hierarchy visible. */
h1, h2, .h1, .h2 {
    font-weight: 700;
    line-height: var(--lh-tight);
    letter-spacing: -0.01em;
}

h3, h4, h5, h6, .h3, .h4, .h5, .h6 {
    font-weight: 700;
    line-height: var(--lh-snug);
}

/* Type-role utilities */
.font-mono  { font-family: var(--font-mono) !important; }
.text-eyebrow {
    font-family: var(--font-mono);
    text-transform: uppercase;
    letter-spacing: 0.14em;
    font-size: var(--fs-xs);
    font-weight: 600;
}

/* Layout */
body {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    /* Reading copy is Georgia, matching the headings. Revert this one
       declaration to var(--font-sans) to put the whole UI back on sans. */
    font-family: var(--font-serif);
}

/* ==========================================================================
   Sans islands

   Georgia is for prose. Controls, navigation and dense data are scanned, not
   read - a serif costs legibility at small sizes and makes form fields and
   tables feel wrong. These stay on the UI face.

   Deliberately NOT listed: .card-body, .lead, and ordinary <p>, which are the
   reading copy this change is for.
   ========================================================================== */

.btn,
.badge,
.form-control,
.form-select,
.form-label,
.form-text,
.form-check-label,
.input-group-text,
input, select, textarea, button,
.navbar, .nav-link, .dropdown-menu, .breadcrumb, .pagination,
.app-sidebar, .sidebar-link, .sidebar-section-title,
.table, table,
.tooltip, .popover,
.text-eyebrow {
    font-family: var(--font-sans);
}

code, kbd, samp, pre {
    font-family: var(--font-mono);
}

/* The writing surfaces are deliberately absent from the lists above.
   entry-form.css pins CodeMirror to a Consolas-first stack with !important
   (CLAUDE.md: relative units and other faces break cursor alignment on iOS),
   and it loads after this file. Nothing here should reach inside the editor. */

.navbar-brand {
    font-weight: 700;
    font-size: 1.5rem;
}

.main-content {
    flex: 1;
}

/* ==========================================================================
   Mood & Sentiment
   ========================================================================== */

.mood-emoji {
    font-size: 1.5rem;
}

.entry-card:hover {
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    transition: box-shadow 0.2s;
}

/* Sentiment colors */
.sentiment-positive { color: #22c55e; }
.sentiment-negative { color: #ef4444; }
.sentiment-neutral { color: #6b7280; }

/* Mood badge colors */
.badge-mood-ecstatic { background-color: var(--secondary-color) !important; color: white; }
.badge-mood-happy { background-color: #22c55e !important; color: white; }
.badge-mood-neutral { background-color: #6b7280 !important; color: white; }
.badge-mood-sad { background-color: #3b82f6 !important; color: white; }
.badge-mood-angry { background-color: #ef4444 !important; color: white; }

/* ==========================================================================
   Opacity utilities (extends Bootstrap's .opacity-25/50/75/100)
   ========================================================================== */

.opacity-70 { opacity: 0.7; }
.opacity-80 { opacity: 0.8; }
.opacity-90 { opacity: 0.9; }

/* ==========================================================================
   POV Blocks
   ========================================================================== */

/* POV blocks - received from friends (light blue) */
.alert-pov {
    background-color: #e0f2fe;
    border: 1px solid #7dd3fc;
    border-left: 4px solid #0ea5e9;
    border-radius: 0.5rem;
    color: #0c4a6e;
}

/* POV blocks must clear floated images above them */
.admonition.admonition-pov,
.admonition.admonition-pov-author,
div.admonition-pov,
div.admonition-pov-author {
    clear: both !important;
    overflow: hidden !important;
    display: block !important;
}

.admonition-pov .admonition-title {
    color: #0369a1;
    font-weight: 600;
}

.admonition-pov .admonition-content {
    color: #0c4a6e;
}

/* POV blocks - sent to friends (light purple) */
.alert-pov-author {
    background-color: #f3e8ff;
    border: 1px solid #d8b4fe;
    border-left: 4px solid #a855f7;
    border-radius: 0.5rem;
    color: #581c87;
}

.admonition-pov-author .admonition-title {
    color: var(--secondary-color);
    font-weight: 600;
}

.admonition-pov-author .admonition-content {
    color: #581c87;
}

/* Images inside POV blocks */
.admonition-pov .admonition-content,
.admonition-pov-author .admonition-content {
    display: flow-root;  /* Creates block formatting context to contain floats */
    position: relative;
    z-index: 1;
}

.admonition-pov .entry-image,
.admonition-pov-author .entry-image {
    margin: 0.5rem 0;
    position: relative;
    z-index: 2;
}

.admonition-pov .entry-image-left,
.admonition-pov-author .entry-image-left {
    margin-right: 1rem;
    margin-bottom: 0.5rem;
}

.admonition-pov .entry-image-right,
.admonition-pov-author .entry-image-right {
    margin-left: 1rem;
    margin-bottom: 0.5rem;
}

.admonition-pov .entry-image img,
.admonition-pov-author .entry-image img {
    border-radius: 6px;
}

/* ==========================================================================
   Tracker Blocks (Goals & Habits)
   ========================================================================== */

.tracker-block {
    display: inline-flex;
    align-items: center;
    padding: 0.35rem 0.75rem;
    border-radius: 0.5rem;
    margin: 0.25rem 0;
    font-size: 0.9rem;
}

.tracker-block a {
    text-decoration: none;
}

.tracker-block a:hover {
    text-decoration: underline;
}

.tracker-goal {
    background-color: var(--status-success-bg);
    border: 1px solid #86efac;
    color: var(--status-success-ink);
}

.tracker-goal a {
    color: var(--status-success-ink);
    font-weight: 500;
}

.tracker-habit {
    background-color: var(--status-warning-bg);
    border: 1px solid #fcd34d;
    color: var(--status-warning-ink);
}

.tracker-habit a {
    color: var(--status-warning-ink);
    font-weight: 500;
}

/* ==========================================================================
   Toast Notifications
   ========================================================================== */

.toast-container {
    position: fixed;
    top: 70px;
    right: 20px;
    z-index: 1050;
    max-width: 300px;
}

.toast-alert {
    padding: 0.5rem 1rem;
    font-size: 0.875rem;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    margin-bottom: 0.5rem;
    animation: slideIn 0.3s ease-out;
}

.toast-alert.alert-success {
    background: var(--status-success-bg);
    color: var(--status-success-ink);
    border: 1px solid var(--status-success-border);
}

.toast-alert.alert-error,
.toast-alert.alert-danger {
    background: var(--status-danger-bg);
    color: var(--status-danger-ink);
    border: 1px solid var(--status-danger-border);
}

.toast-alert.alert-warning {
    background: var(--status-warning-bg);
    color: var(--status-warning-ink);
    border: 1px solid var(--status-warning-border);
}

.toast-alert.alert-info {
    background: var(--status-info-bg);
    color: var(--status-info-ink);
    border: 1px solid var(--status-info-border);
}

.toast-alert .btn-close {
    padding: 0.25rem;
    font-size: 0.7rem;
}

@keyframes slideIn {
    from { transform: translateX(100%); opacity: 0; }
    to { transform: translateX(0); opacity: 1; }
}

@keyframes slideOut {
    from { transform: translateX(0); opacity: 1; }
    to { transform: translateX(100%); opacity: 0; }
}

.toast-alert.hiding {
    animation: slideOut 0.3s ease-in forwards;
}

/* ==========================================================================
   Mobile Navigation
   ========================================================================== */

@media (max-width: 991.98px) {
    .navbar-collapse.show,
    .navbar-collapse.collapsing {
        position: fixed;
        top: 56px;
        left: 0;
        right: 0;
        bottom: 0;
        background: #1f2937;
        padding: 1rem;
        overflow-y: auto;
        z-index: 1050;
    }

    .navbar-collapse.show .navbar-nav,
    .navbar-collapse.collapsing .navbar-nav {
        flex-direction: column !important;
    }

    .navbar-collapse.show .nav-item,
    .navbar-collapse.collapsing .nav-item {
        width: 100%;
        border-bottom: 1px solid rgba(255,255,255,0.1);
    }

    .navbar-collapse.show .nav-link,
    .navbar-collapse.collapsing .nav-link {
        padding: 0.75rem 0.5rem;
        font-size: 1rem;
    }

    .navbar-collapse.show .dropdown-menu {
        position: static !important;
        background: transparent;
        border: none;
        padding-left: 1rem;
        box-shadow: none;
    }

    .navbar-collapse.show .dropdown-item {
        color: rgba(255,255,255,0.8);
        padding: 0.5rem;
    }

    .navbar-collapse.show .dropdown-item:hover {
        background: rgba(255,255,255,0.1);
        color: white;
    }

    .navbar-collapse.show .dropdown-divider {
        border-color: rgba(255,255,255,0.1);
    }

    .navbar-collapse.show .ms-auto {
        margin-left: 0 !important;
        margin-top: 1rem;
        padding-top: 1rem;
        border-top: 1px solid rgba(255,255,255,0.2);
    }
}

/* ==========================================================================
   Feedback FAB Button

   The button's own geometry lives in layouts/global.css, which positions the
   .feedback-fab-container and has the responsive sizing. A duplicate
   position/size block used to sit here; because base.css loads AFTER
   global.css it beat those media queries, so the FAB never shrank or moved on
   mobile and sat 8px off from the New Entry FAB stacked above it.
   ========================================================================== */

#feedbackModal .btn-group .btn {
    flex: 1;
    font-size: 0.875rem;
    padding: 0.5rem;
}

/* ==========================================================================
   Entry Images
   ========================================================================== */

.entry-image {
    margin: 1rem 0;
}

.entry-image img {
    max-width: 100%;
    height: auto;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.entry-image figcaption {
    font-size: 0.85rem;
    color: #6b7280;
    margin-top: 0.5rem;
    text-align: center;
}

.entry-image-left {
    float: left;
    margin-right: 1.5rem;
    margin-bottom: 1rem;
}

.entry-image-right {
    float: right;
    margin-left: 1.5rem;
    margin-bottom: 1rem;
}

.entry-image-center {
    display: block;
    margin-left: auto;
    margin-right: auto;
    text-align: center;
}

/* Clear floats after images */
.entry-content::after {
    content: "";
    display: table;
    clear: both;
}
