/* Material Design 3 token palette (light theme). These are the same
   --md-sys-color-* / --md-sys-shape-* custom properties Material Web
   components themselves read, applied here to :root so both the MWC
   components AND the hand-built layout (app shell, panes, list rows -
   MWC has no app-bar/card/page-layout components, only discrete
   interactive ones) share one consistent token system rather than two
   competing color systems. Values are a standard M3 baseline blue scheme,
   not a custom brand palette - swap here if that's ever wanted, nothing
   below this block references a literal color. */
:root {
    --md-sys-color-primary: #3457d5;
    --md-sys-color-on-primary: #ffffff;
    --md-sys-color-primary-container: #dee1ff;
    --md-sys-color-on-primary-container: #00105c;

    --md-sys-color-surface: #fdfbff;
    --md-sys-color-on-surface: #1b1b1f;
    --md-sys-color-surface-variant: #e3e1ec;
    --md-sys-color-on-surface-variant: #46464f;
    --md-sys-color-surface-container-lowest: #ffffff;
    --md-sys-color-surface-container-low: #f7f5fa;
    --md-sys-color-surface-container: #f2f0f5;
    --md-sys-color-surface-container-high: #ecebf0;

    --md-sys-color-outline: #777680;
    --md-sys-color-outline-variant: #c7c5d0;

    --md-sys-color-error: #ba1a1a;
    --md-sys-color-on-error: #ffffff;
    --md-sys-color-error-container: #ffdad6;
    --md-sys-color-on-error-container: #410002;

    --md-sys-shape-corner-small: 8px;
    --md-sys-shape-corner-medium: 12px;
    --md-sys-shape-corner-large: 16px;
    --md-sys-shape-corner-extra-large: 28px;

    font-family: Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

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

body {
    margin: 0;
    background: var(--md-sys-color-surface-container-lowest);
    color: var(--md-sys-color-on-surface);
    height: 100vh;
    overflow: hidden;
}

/* ---- Login page ---- */

/* <html> is the actual root scroller in standards mode - overflow-x:hidden
   on <body> alone doesn't reliably stop it from propagating a horizontal
   scrollbar up to the viewport, so it needs setting here explicitly too.
   Scoped to the login page only via this class (not a bare `html`
   selector, which would also affect the main app page sharing this same
   stylesheet). */
html.login-page {
    overflow-x: hidden;
}

.login-body {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    /* The backdrop graphic deliberately bleeds off the right edge -
       overflow-x clips that rather than growing a horizontal scrollbar;
       overflow-y stays scrollable for a viewport too short to fit the
       form. */
    overflow-x: hidden;
    overflow-y: auto;
    padding: 16px;
    background: var(--md-sys-color-surface-container-low);
}

/* Decorative backdrop, clamped to viewport width so it can't force a
   scrollbar. fill/opacity are set inline in login.html, not here. */
.login-backdrop {
    position: absolute;
    top: 6%;
    right: 6%;
    z-index: 0;
    width: min(640px, 85vw);
    height: min(640px, 85vw);
    transform: rotate(-8deg);
    pointer-events: none;
}

/* Wider than the form itself (see #login-form below) - the title/subtitle
   use this full width and center-align, while the form is capped
   narrower and also centered, so the header visibly extends past the
   form's edges by the same amount on both sides. No background/border/
   shadow - the form sits directly on the page rather than inside a boxed
   card. */
.login-card {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 460px;
    padding: 32px;
    /* .login-body centers this via flex align-items - a bottom margin on
       the centered item shifts its visual center upward (flex centers
       the margin box, not just the content), pushing the whole card up
       from true vertical center without touching the flex container
       itself. */
    margin-bottom: 72px;
    text-align: center;
}

/* Matches login.html's Turnstile breakpoint (native "compact" widget
   below 480px) - sized down to suit, not just the widget shrinking
   inside an otherwise full-size card. */
@media (max-width: 480px) {
    .login-card {
        max-width: 380px;
        padding: 24px 20px;
    }
}

/* Narrower than .login-card and centered within it - sized around
   Turnstile's own fixed 300px widget plus breathing room, same as the
   card's own width used to be before the header was widened. */
#login-form {
    max-width: 340px;
    margin: 0 auto;
    text-align: left;
}

#turnstile-container {
    margin-bottom: 12px;
}

.login-card h1 {
    margin: 0 0 8px;
    font-size: 32px;
    font-weight: 500;
}

.login-sub {
    /* Matches .group's own margin-bottom (32px) so the first field's
       floated label gets the same clearance above it that every later
       field already gets from the group before it - otherwise it's
       only got .login-sub's own margin to float into, which reads as
       cramped/touching the moment the label lifts. */
    margin: 0 0 32px;
    font-size: 15px;
    color: var(--md-sys-color-on-surface-variant);
    font-size: 13px;
}

/* Plain native <input>, not md-outlined-text-field - a real DOM input is
   what browser autofill and password managers actually need to see (most
   don't reliably detect or offer to save credentials for a field whose
   real <input> is hidden inside a custom element's shadow DOM).
   Classic floating-label technique: label/bar/highlight are siblings
   AFTER the input (not wrapping it), so `~` sibling selectors can react
   to the input's :focus/:not(:placeholder-shown) state with no JS.
   `:not(:placeholder-shown)` (not `:valid`) drives the float - a
   required type="email" field is :invalid while a partial address is
   still being typed, which would otherwise leave the label sunk back
   down over already-entered text the moment the field loses focus. */
.group {
    position: relative;
    margin-bottom: 32px;
}

.group input {
    box-sizing: border-box;
    width: 100%;
    font: inherit;
    font-size: 16px;
    padding: 10px 2px;
    display: block;
    background: transparent;
    color: var(--md-sys-color-on-surface);
    border: none;
    border-bottom: 1px solid var(--md-sys-color-outline);
}

.group input:focus {
    outline: none;
}

.group label {
    position: absolute;
    left: 2px;
    top: 10px;
    font-size: 16px;
    color: var(--md-sys-color-on-surface-variant);
    pointer-events: none;
    transition: 0.2s ease all;
}

.group input:focus ~ label,
.group input:not(:placeholder-shown) ~ label {
    top: -18px;
    font-size: 12px;
    color: var(--md-sys-color-primary);
}

.group .bar {
    position: relative;
    display: block;
    width: 100%;
}

.group .bar::before,
.group .bar::after {
    content: "";
    position: absolute;
    bottom: 1px;
    width: 0;
    height: 2px;
    background: var(--md-sys-color-primary);
    transition: 0.2s ease all;
}

.group .bar::before { left: 50%; }
.group .bar::after { right: 50%; }

.group input:focus ~ .bar::before,
.group input:focus ~ .bar::after {
    width: 50%;
}

.group .highlight {
    position: absolute;
    top: 25%;
    left: 0;
    width: 100px;
    height: 60%;
    pointer-events: none;
    opacity: 0.5;
}

.group input:focus ~ .highlight {
    animation: inputHighlighter 0.3s ease;
}

@keyframes inputHighlighter {
    from { background: var(--md-sys-color-primary); }
    to { width: 0; background: transparent; }
}

#login-form md-filled-button {
    width: 100%;
}

.btn-spinner {
    display: inline-block;
    width: 15px;
    height: 15px;
    margin-right: 8px;
    vertical-align: -3px;
    border: 2px solid rgba(255, 255, 255, 0.4);
    border-top-color: #fff;
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}

/* The class above sets its own `display`, which - being an author-origin
   rule - overrides the browser's default `[hidden] { display: none }`
   UA-stylesheet rule. Without this, the spinner shows immediately on page
   load (the `hidden` attribute present in the markup gets silently
   defeated the moment .btn-spinner's own `display` also applies). */
.btn-spinner[hidden] {
    display: none;
}

.error-text {
    color: var(--md-sys-color-error);
    font-size: 13px;
    margin: 10px 0 0;
}

/* ---- App shell ---- */

.app-grid {
    display: grid;
    grid-template-columns: 240px 340px 1fr;
    grid-template-rows: 64px 1fr;
    grid-template-areas:
        "header header header"
        "sidebar list reader";
    height: 100vh;
}

/* Message list fills the remaining width until a message is open, then
   splits into the familiar list+reader panes - matching Gmail/Proton
   rather than always showing a half-empty reader pane. The reader area
   itself never leaves the grid (same 3 track slots throughout, only the
   size values change) specifically so grid-template-columns stays
   animatable - Chrome/Firefox don't interpolate a track being added or
   removed, only existing tracks resizing. min-width:900px keeps this
   scoped away from the mobile breakpoint below, which already has its
   own single-pane list/reader swap that this must not fight with. */
@media (min-width: 901px) {
    .app-grid {
        transition: grid-template-columns 0.22s ease;
    }
    .app-grid.no-message-open {
        grid-template-columns: 240px 1fr 0px;
    }
    .app-grid.no-message-open .reader {
        overflow: hidden;
    }
}

.app-header {
    grid-area: header;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 20px;
    background: var(--md-sys-color-surface-container-lowest);
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
}

.app-header h1 {
    font-size: 17px;
    font-weight: 500;
    margin: 0;
}

.app-header .header-right {
    display: flex;
    align-items: center;
    gap: 12px;
}

.logged-in-as {
    font-size: 13px;
    color: var(--md-sys-color-on-surface-variant);
}

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

#refresh-btn.spinning md-icon {
    display: inline-block;
    animation: spin 0.8s linear infinite;
}

.sidebar {
    grid-area: sidebar;
    background: var(--md-sys-color-surface-container-lowest);
    border-right: 1px solid var(--md-sys-color-outline-variant);
    overflow-y: auto;
    padding: 8px;
}

.sidebar md-list {
    background: transparent;
    --md-list-container-color: transparent;
}

md-list-item.folder-item {
    border-radius: var(--md-sys-shape-corner-large);
    --md-list-item-label-text-color: var(--md-sys-color-on-surface-variant);
}

md-list-item.folder-item.active {
    background: var(--md-sys-color-primary-container);
    --md-list-item-label-text-color: var(--md-sys-color-on-primary-container);
    --md-list-item-label-text-weight: 600;
}

.message-list {
    grid-area: list;
    background: var(--md-sys-color-surface-container-lowest);
    border-right: 1px solid var(--md-sys-color-outline-variant);
    overflow-y: auto;
}

.message-list md-list {
    background: transparent;
    padding: 0;
}

md-list-item.message-item {
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
}

md-list-item.message-item.active {
    background: var(--md-sys-color-secondary-container, var(--md-sys-color-primary-container));
}

md-list-item.message-item.unread {
    --md-list-item-label-text-weight: 700;
    --md-list-item-supporting-text-weight: 700;
}

/* Sender/subject text can be arbitrarily long (a real address, a real
   subject line) - truncate to one line each with ellipsis rather than
   wrapping, which would otherwise push the trailing date down onto its
   own line and make rows an unpredictable height. */
md-list-item.message-item [slot="headline"],
md-list-item.message-item [slot="supporting-text"] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.msg-date {
    font-size: 12px;
    color: var(--md-sys-color-on-surface-variant);
    white-space: nowrap;
}

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

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

.fade-in {
    animation: fade-in 0.18s ease;
}

.skeleton-line,
.skeleton-block {
    display: block;
    border-radius: 4px;
    background: linear-gradient(90deg,
        var(--md-sys-color-surface-container) 25%,
        var(--md-sys-color-surface-container-high) 50%,
        var(--md-sys-color-surface-container) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.4s ease-in-out infinite;
}

.skeleton-row {
    padding: 12px 16px;
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
}

.skeleton-row .skeleton-line-title {
    width: 55%;
    height: 11px;
    margin-bottom: 8px;
}

.skeleton-row .skeleton-line-sub {
    width: 85%;
    height: 9px;
}

.skeleton-reader {
    padding: 20px 24px;
}

.skeleton-line-subject {
    width: 40%;
    height: 16px;
    margin-bottom: 14px;
}

.skeleton-line-meta {
    width: 30%;
    height: 10px;
    margin-bottom: 24px;
}

.skeleton-block {
    width: 100%;
    height: 200px;
}

.unread-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--md-sys-color-primary);
}

.empty-state {
    padding: 32px 16px;
    color: var(--md-sys-color-on-surface-variant);
    font-size: 13px;
    text-align: center;
}

.reader {
    grid-area: reader;
    background: var(--md-sys-color-surface-container-low);
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}

.reader-header {
    padding: 20px 24px 16px;
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
    background: var(--md-sys-color-surface-container-lowest);
}

.reader-header h2 {
    margin: 0 0 10px;
    font-size: 18px;
    font-weight: 500;
}

.back-to-list-btn {
    display: none;
    margin-bottom: 4px;
}

.reader-meta {
    font-size: 13px;
    color: var(--md-sys-color-on-surface-variant);
    line-height: 1.7;
}

.reader-actions {
    margin-top: 12px;
    display: flex;
    gap: 8px;
}

.reader-body {
    flex: 1;
    padding: 16px 24px;
}

.reader-frame {
    width: 100%;
    height: 100%;
    min-height: 300px;
    border: 1px solid var(--md-sys-color-outline-variant);
    border-radius: var(--md-sys-shape-corner-medium);
    background: #fff;
}

.attachments {
    margin-top: 14px;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.attachment-chip {
    font: inherit;
    font-size: 12px;
    padding: 6px 12px;
    border: 1px solid var(--md-sys-color-outline-variant);
    border-radius: 20px;
    background: var(--md-sys-color-surface-container);
    color: var(--md-sys-color-on-surface-variant);
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* Reader attachment chips double as the download control - a real <button>
   (see app.js), styled to still read as a chip rather than a form control. */
button.attachment-chip {
    cursor: pointer;
}

button.attachment-chip:hover {
    background: var(--md-sys-color-surface-container-high);
    border-color: var(--md-sys-color-outline);
}

.attachment-chip .remove-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    border: none;
    border-radius: 50%;
    padding: 0;
    background: transparent;
    color: inherit;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
}

.attachment-chip .remove-chip:hover {
    background: var(--md-sys-color-surface-container-high);
}

/* ---- Compose dialog ---- */

/* md-dialog has no width/min-width/max-width design tokens (confirmed
   against the docs - --md-dialog-container-max-width doesn't exist,
   an earlier attempt at this that silently did nothing since it's not a
   real custom property MWC reads) and the host element itself renders
   with display:contents, so it has no box of its own to size via CSS
   either. MD3 dialogs size to fit their slotted content instead - the
   real fix is giving the content slot's own element (ours, not MWC's)
   an explicit width, which the dialog then wraps around. */
.compose-fields {
    width: 480px;
    max-width: calc(90vw - 48px);
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.compose-fields md-outlined-text-field,
.compose-fields md-filled-text-field {
    width: 100%;
}

.compose-attach-row {
    margin-top: -8px;
}

/* Capped rather than left to grow with however many files are attached -
   md-dialog's own internal max-height (see the block below) leaves this
   whole dialog a fixed content budget, so an unbounded chip list would
   eventually force the dialog itself to scroll instead of just this list.
   min-height:0 overrides the flex-item default of min-height:auto (which
   sizes a flex child to its content regardless of max-height) - without it
   this max-height/overflow pair is silently ignored in a column flex
   container like .compose-fields. */
.compose-attachment-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    max-height: 56px;
    min-height: 0;
    overflow-y: auto;
}

.compose-attachment-list:empty {
    display: none;
}

.status-text {
    font-size: 12px;
    color: var(--md-sys-color-on-surface-variant);
    align-self: center;
    margin-right: auto;
}

.status-text.error { color: var(--md-sys-color-error); }

@media (max-width: 900px) {
    /* Single content row, not stacked list+reader rows - an "auto" row sized
       by message-list's natural content height (which can exceed the
       viewport for a realistic-length list) previously starved the "1fr"
       reader row down to 0px the moment there were enough messages to fill
       the screen. list and reader now share one row and only one is shown
       at a time (app.js toggles .reader-open), each scrolling internally
       exactly like the desktop panes already do. */
    .app-grid {
        grid-template-columns: 1fr;
        grid-template-rows: 64px 1fr;
        grid-template-areas:
            "header"
            "content";
    }
    .sidebar { display: none; }

    .message-list, .reader {
        grid-area: content;
    }
    .message-list { display: block; }
    .reader { display: none; }
    .app-grid.reader-open .message-list { display: none; }
    .app-grid.reader-open .reader { display: flex; }

    .back-to-list-btn { display: inline-flex; }

    /* Compose lives in the header (always reachable) on every viewport
       size - no mobile-specific override needed here beyond the sidebar
       (its old home) being hidden above. */

    /* The logged-in email address is the least essential header item and
       the one most likely to be long enough to force everything else
       (refresh, Compose, Log out) to wrap or get squeezed - dropped here
       rather than letting it compete for space on a narrow screen. */
    .logged-in-as { display: none; }
}

/* ============================================================================
   Sidebar collapse + Settings (2026-08-26)
   ========================================================================= */

/* The sidebar becomes a flex column so the collapse toggle can pin to the
   bottom; the folder list keeps all remaining height. */
.sidebar {
    display: flex;
    flex-direction: column;
}
.sidebar md-list {
    flex: 1;
}
#sidebar-toggle {
    align-self: flex-end;
    margin-top: auto;
}

/* Collapse only exists at the desktop breakpoint - below 901px the whole
   sidebar is display:none (mobile layout) and these rules must not leak
   into the single-column grid there. */
@media (min-width: 901px) {
    .app-grid.sidebar-collapsed {
        grid-template-columns: 68px 340px 1fr;
    }
    .app-grid.sidebar-collapsed.no-message-open {
        grid-template-columns: 68px 1fr 0px;
    }
    .app-grid.sidebar-collapsed .folder-label {
        display: none;
    }
    /* overflow:visible so the flyout tooltips aren't clipped by the narrow
       rail. Tradeoff: a very long folder list won't scroll while collapsed -
       acceptable for the handful of IMAP folders a mailbox has. */
    .app-grid.sidebar-collapsed .sidebar {
        overflow: visible;
        padding: 8px 6px;
    }
    .app-grid.sidebar-collapsed md-list-item.folder-item {
        --md-list-item-leading-space: 14px;
        --md-list-item-trailing-space: 0px;
    }
    /* Flyout tooltip with the folder's real name, collapsed mode only.
       Shows on hover and keyboard focus; on touch, a tap navigates (the
       native title attribute still covers long-press). */
    .app-grid.sidebar-collapsed .folder-item {
        position: relative;
    }
    .app-grid.sidebar-collapsed .folder-item:hover::after,
    .app-grid.sidebar-collapsed .folder-item:focus-within::after {
        content: attr(data-tip);
        position: absolute;
        left: calc(100% + 10px);
        top: 50%;
        transform: translateY(-50%);
        background: var(--md-sys-color-inverse-surface);
        color: var(--md-sys-color-inverse-on-surface);
        padding: 4px 10px;
        border-radius: 6px;
        font-size: 12px;
        white-space: nowrap;
        z-index: 60;
        pointer-events: none;
    }
}

/* Settings: full-page overlay above the app. display:flex would defeat the
   `hidden` attribute, so the [hidden] rule below is load-bearing. */
.settings-modal {
    position: fixed;
    inset: 0;
    z-index: 200;
    background: var(--md-sys-color-surface);
    display: flex;
    flex-direction: column;
}
.settings-modal[hidden] {
    display: none;
}
.settings-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 64px;
    padding: 0 20px;
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
    background: var(--md-sys-color-surface-container-lowest);
}
.settings-header h2 {
    font-size: 17px;
    font-weight: 500;
    margin: 0;
}
.settings-content {
    width: 100%;
    max-width: 640px;
    margin: 0 auto;
    padding: 24px 20px;
    overflow-y: auto;
}
/* One setting per row; the whole row is the tap target (it's a <label>, so
   tapping anywhere flips the switch) - comfortable on touch. */
.settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    padding: 16px 4px;
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
    cursor: pointer;
}
.settings-row-title {
    font-size: 15px;
    color: var(--md-sys-color-on-surface);
}
.settings-row-desc {
    font-size: 13px;
    line-height: 1.4;
    margin-top: 2px;
    color: var(--md-sys-color-on-surface-variant);
}

/* --- Settings: change password ------------------------------------------ */
/* No border here: .settings-row above already ends in a border-bottom, and
   adding one produced two stacked divider lines. */
.settings-section {
    margin-top: 20px;
    padding-top: 20px;
}
.settings-form {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-top: 14px;
}
.settings-field {
    display: flex;
    flex-direction: column;
    gap: 5px;
    font-size: 13px;
}
.settings-field input {
    padding: 9px 11px;
    border: 1px solid var(--md-sys-color-outline, #79747e);
    border-radius: 6px;
    background: var(--md-sys-color-surface, #fff);
    color: var(--md-sys-color-on-surface, #1c1b1f);
    font-size: 14px;
    font-family: inherit;
}
.settings-field input:focus-visible {
    outline: 2px solid var(--md-sys-color-primary, #6750a4);
    outline-offset: 1px;
}
.settings-hint {
    font-size: 12px;
    opacity: 0.7;
}
.settings-button {
    align-self: flex-start;
    padding: 9px 18px;
    border: none;
    border-radius: 20px;
    background: var(--md-sys-color-primary, #6750a4);
    color: var(--md-sys-color-on-primary, #fff);
    font-size: 14px;
    font-family: inherit;
    cursor: pointer;
}
.settings-button:disabled { opacity: 0.6; cursor: default; }
.settings-message {
    font-size: 13px;
    padding: 9px 11px;
    border-radius: 6px;
}
.settings-message-ok    { background: #e6f4ea; color: #12633b; }
.settings-message-error { background: #fce8e6; color: #a50e0e; }

.pw-input-wrap { position: relative; display: flex; align-items: center; }
.pw-input-wrap input { width: 100%; padding-right: 44px; }
.pw-reveal {
    position: absolute;
    right: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--md-sys-color-on-surface-variant, #49454f);
    cursor: pointer;
}
.pw-reveal:hover { background: rgba(0, 0, 0, 0.06); }
.pw-reveal md-icon { font-size: 20px; }
