/**
 * App styles — the `@layer app` slot.
 *
 * The app's own structural and domain CSS. Sits below `theme`, so a theme can
 * restate a colour or radius without fighting these rules, and above
 * `components`, so a `ui-*` / `civ-*` element can still be placed in a layout.
 *
 * Tokens belong in `theme.css`; setting one here will not win.
 */

@layer app {
  /* ── Grain — a faint fixed noise field over the stage, not the content;
       keeps the near-black from reading as a flat, dead void. ─────────── */
  body {
    background-color: hsl(var(--backgroundH) var(--backgroundS)
      var(--backgroundL));
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
    background-repeat: repeat;
    font-family: var(--font-family-base);
  }

  h1,
  h2,
  h3 {
    font-family: var(--font-family-display);
    color: hsl(var(--headingH) var(--headingS) var(--headingL));
    letter-spacing: -0.01em;
  }

  /* <main> itself carries zero padding (--main-padding: 0, above) so the
     photo stage can bleed edge-to-edge; every route's own root <section>
     gets the actual content inset. */
  main section {
    padding: 0 var(--s3);
    box-sizing: border-box;
  }

  /* Settings is a stack of subjects — the scenes contribute one `<section>`
     each, so the rhythm has to come from the page rather than from any one of
     them. `main section` above only insets; this spaces. */
  r-settings > *,
  r-settings-sync > * {
    display: block;
    margin-bottom: var(--s5);
  }

  /* ── Header ────────────────────────────────────────────────────────── */
  header {
    display: flex;
    align-items: center;
    gap: var(--s3);
    height: var(--header-height);
    padding: 0 var(--container-padding);
    border-bottom: 1px solid hsl(var(--borderH) var(--borderS) var(--borderL) /
      0.6);
    background: hsl(var(--backgroundH) var(--backgroundS) var(--backgroundL));
  }

  /* Every per-route header landmark (p-header, p-library-header,
     p-album-header, p-photo-header) lays out the same way: an optional back
     button, a flexible title, and trailing actions — see each component for
     what actually fills those slots. */
  p-header,
  p-library-header,
  p-album-header,
  p-photo-header {
    display: contents;
  }

  header h1 {
    flex: 1;
    /* A flex item's default `min-width: auto` floors its shrink at its
       content size — with `white-space: nowrap` that's the full title, so
       without this a long caption or tag name pushes the header (and the
       page) wider than the viewport instead of ellipsizing. */
    min-width: 0;
    margin: 0;
    font-size: var(--f2);
    font-style: italic;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* The Library route keeps the "PhotoApp" brand mark instead of a plain
     route title — it's the app's one persistent/home route. */
  header h1.brand {
    font-style: normal;
    font-weight: var(--fw-medium);
  }

  header h1.brand em {
    font-style: italic;
    font-weight: 500;
    color: hsl(var(--brand-primaryH) var(--brand-primaryS)
      var(--brand-primaryL));
  }

  .header-back {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background: transparent;
    border: none;
    padding: var(--s1);
    color: hsl(var(--brand-primaryH) var(--brand-primaryS)
      var(--brand-primaryL));
    cursor: pointer;
  }

  .header-actions {
    display: flex;
    align-items: center;
    gap: var(--s3);
    flex-shrink: 0;
  }

  .header-actions .readout {
    white-space: nowrap;
  }

  /* ── Fixed bottom tab bar ──────────────────────────────────────────── */
  footer[fixed] {
    padding: 0;
    height: var(--footer-height);
    background: hsl(var(--backgroundH) var(--backgroundS) var(--backgroundL));
    border-top: 1px solid hsl(var(--borderH) var(--borderS) var(--borderL) /
      0.6);
  }

  ui-bottom-bar a {
    color: hsl(var(--secondaryH) var(--secondaryS) var(--secondaryL));
    transition: color var(--transition-base);
  }

  ui-bottom-bar a[aria-current='page'] {
    color: hsl(var(--brand-primaryH) var(--brand-primaryS)
      var(--brand-primaryL));
  }

  ui-bottom-bar a span:last-child {
    font-size: var(--f7);
    font-weight: var(--fw-medium);
  }

  .readout {
    font-family: var(--font-family-mono);
    font-size: var(--f6);
    letter-spacing: 0.02em;
    color: hsl(var(--secondaryH) var(--secondaryS) var(--secondaryL));
  }

  /* Primary action — the one filled, glowing control in the app. */
  .action {
    display: inline-flex;
    align-items: center;
    gap: var(--s2);
    padding: var(--s2) var(--s3);
    border: none;
    border-radius: var(--br-full);
    background: hsl(var(--brand-primaryH) var(--brand-primaryS)
      var(--brand-primaryL));
    color: var(--brand-ink);
    font-weight: var(--fw-semibold);
    font-size: var(--f5);
    cursor: pointer;
    box-shadow: var(--shadow-brand);
    transition: transform var(--transition-fast), box-shadow
      var(--transition-base);
  }

  .action:hover {
    transform: translateY(-1px);
    box-shadow: 0 8px 24px -4px hsl(36 92% 55% / 0.45);
  }

  .action:active {
    transform: translateY(0);
  }

  .action.disabled {
    opacity: 0.5;
    pointer-events: none;
    box-shadow: none;
  }

  /* Text-only controls — anchors already look like this natively; buttons
     need the browser's default border/padding/background stripped so a
     <button class="link"> matches an <a class="link"> exactly. */
  button.link {
    appearance: none;
    -webkit-appearance: none;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    cursor: pointer;
    transition: none;
  }

  button.link:hover {
    transform: none;
    opacity: 0.75;
  }

  .link {
    color: hsl(var(--brand-primaryH) var(--brand-primaryS)
      var(--brand-primaryL));
    font-weight: var(--fw-medium);
    /* Was inherited from utilities.css, removed in 0.12. */
    text-decoration: none;
  }

  .link.danger {
    color: hsl(var(--errorH) var(--errorS) var(--errorL));
  }

  .link.icon-only {
    display: inline-flex;
    align-items: center;
  }

  /* Form fields ship with no background in the base layer, so they fall
     back to the platform's native (light) control color — jarring on a
     dark stage. Every text-like input in this app should read as part of
     the room, not a punched-out hole in it. */
  input[type='text'],
  input[type='email'],
  input[type='password'],
  input[type='number'],
  input[type='search'],
  input[type='url'],
  input[type='tel'],
  textarea,
  select {
    background: var(--surface);
    color: hsl(var(--bodyH) var(--bodyS) var(--bodyL));
    border-color: hsl(var(--borderH) var(--borderS) var(--borderL));
  }

  /* ── Library / Albums select-mode toolbar (now in the header) ──────── */
  .toolbar-group {
    display: flex;
    align-items: center;
    gap: var(--s3);
  }

  .select-all {
    display: inline-flex;
    align-items: center;
    gap: var(--s2);
    font-size: var(--f5);
    color: hsl(var(--secondaryH) var(--secondaryS) var(--secondaryL));
  }

  /* ── Photo grid (library day-groups, album detail) ────────────────── */
  .photo-grid-group {
    margin-top: var(--s5);
  }

  .photo-grid-group:first-child {
    margin-top: var(--s4);
  }

  .photo-grid-header {
    font-family: var(--font-family-mono);
    font-size: var(--f7);
    font-weight: var(--fw-medium);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: hsl(var(--secondaryH) var(--secondaryS) var(--secondaryL));
    margin-bottom: var(--s2);
  }

  .photo-grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
    gap: 3px;
  }

  .photo-tile a {
    display: block;
  }

  .photo-tile img {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var(--br-sm);
    background: var(--surface);
    transition: transform var(--transition-base), filter var(--transition-base);
  }

  .photo-tile a:hover img {
    transform: scale(1.03);
    filter: brightness(1.06);
  }

  /* Select mode: the tile becomes a toggle button instead of a link — same
     square image, plus a checkmark badge in the corner. */
  .photo-tile-select {
    position: relative;
    display: block;
    width: 100%;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
  }

  .photo-tile-select.checked img {
    opacity: 0.5;
  }

  .photo-tile-check {
    position: absolute;
    top: var(--s1);
    right: var(--s1);
    width: 1.25rem;
    height: 1.25rem;
    border-radius: var(--br-full);
    border: 2px solid hsl(var(--whiteH) var(--whiteS) var(--whiteL) / 0.85);
    background: rgba(6, 4, 2, 0.35);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  }

  .photo-tile-select.checked .photo-tile-check {
    background: hsl(var(--brand-primaryH) var(--brand-primaryS)
      var(--brand-primaryL));
    border-color: hsl(var(--brand-primaryH) var(--brand-primaryS)
      var(--brand-primaryL));
  }

  .photo-tile-select.checked .photo-tile-check::after {
    content: "✓";
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.7rem;
    font-weight: var(--fw-bold);
    color: var(--brand-ink);
  }

  /* ── Albums index ──────────────────────────────────────────────────── */
  .album-grid {
    list-style: none;
    margin: var(--s3) 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: var(--s4);
  }

  .album-tile a {
    display: flex;
    flex-direction: column;
    gap: var(--s1);
    text-decoration: none;
    color: inherit;
  }

  .album-tile img {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var(--br-lg);
    border: 1px solid hsl(var(--borderH) var(--borderS) var(--borderL));
    transition: transform var(--transition-base);
  }

  .album-tile a:hover img {
    transform: translateY(-2px);
  }

  .album-tile strong {
    font-family: var(--font-family-display);
    font-style: italic;
    font-weight: 500;
    font-size: var(--f4);
    margin-top: var(--s1);
  }

  .album-tile .muted {
    font-family: var(--font-family-mono);
    font-size: var(--f7);
  }

  /* ── Photo viewer ──────────────────────────────────────────────────── */
  .photo-view {
    display: flex;
    flex-direction: column;
    gap: var(--s4);
  }

  /* The one deliberate bleed: pull just the image stage back out past the
     section's inset so the photo runs edge-to-edge, like a slide filling a
     projector screen, while the caption/tags/EXIF stay in the normal
     padded column below it.

     Collapsed, the stage fills exactly the space between header and
     footer — the photo alone, centered, nothing else to look at or scroll
     to. A click, scroll, or swipe (photo.ts) reveals `.photo-meta` below
     and shrinks the stage to match in one motion. */
  .photo-stage {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 calc(var(--s3) * -1);
    background: var(--surface);
    overflow: hidden;
    height: calc(100vh - var(--header-height) - var(--footer-height));
    height: calc(100dvh - var(--header-height) - var(--footer-height));
    transition: height 0.45s cubic-bezier(0.4, 0, 0.2, 1);
  }

  .photo-stage.expanded {
    height: 56vh;
  }

  /* `width`/`height` attributes (photo.ts) carry the real dimensions, so the
     browser reserves this box's aspect ratio before a single byte of the
     image has arrived — no layout shift once it decodes. */
  .photo-full {
    display: block;
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
    cursor: pointer;
  }

  .reveal-hint {
    position: absolute;
    bottom: var(--s3);
    left: 50%;
    transform: translateX(-50%);
    z-index: 2;
    width: 2.25rem;
    height: 2.25rem;
    border: none;
    border-radius: var(--br-full);
    background: rgba(6, 4, 2, 0.45);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    color: hsl(var(--whiteH) var(--whiteS) var(--whiteL));
    font-size: var(--f2);
    line-height: 1;
    cursor: pointer;
    animation: reveal-bounce 2.2s ease-in-out infinite;
  }
  @keyframes reveal-bounce {
    0%,
    100% {
      transform: translateX(-50%) translateY(0);
    }
    50% {
      transform: translateX(-50%) translateY(6px);
    }
  }

  .photo-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    font-size: var(--f1);
    line-height: 1;
    text-decoration: none;
    color: hsl(var(--whiteH) var(--whiteS) var(--whiteL));
    background: rgba(6, 4, 2, 0.45);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border-radius: var(--br-full);
    width: 2.5rem;
    height: 2.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 1;
    transition: background var(--transition-base), opacity 0.4s ease;
  }

  .photo-nav:hover {
    background: rgba(6, 4, 2, 0.7);
  }

  /* Faded out after a few seconds of no mouse movement (photo.ts) — left up
     indefinitely, these sit over part of a landscape photo. */
  .photo-nav.idle {
    opacity: 0;
    pointer-events: none;
  }

  .photo-nav.prev {
    left: var(--s2);
  }

  .photo-nav.next {
    right: var(--s2);
  }

  /* ── Metadata reveal ───────────────────────────────────────────────── */
  /* `grid-template-rows: 0fr → 1fr` animates to an unknown content height
     (EXIF line count varies per photo) without a JS-measured pixel value —
     `.photo-meta-inner` is the single grid item that gets clipped while the
     row track is collapsed. */
  .photo-meta {
    display: grid;
    grid-template-rows: 0fr;
    opacity: 0;
    transition:
      grid-template-rows 0.45s cubic-bezier(0.4, 0, 0.2, 1),
      opacity 0.35s ease;
  }

  .photo-meta.expanded {
    grid-template-rows: 1fr;
    opacity: 1;
  }

  .photo-meta-inner {
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: var(--s4);
  }

  /* ── Caption + tags panel ──────────────────────────────────────────── */
  .photo-panel {
    display: flex;
    flex-direction: column;
    gap: var(--s3);
    padding: var(--s3);
    background: var(--surface);
    border-radius: var(--br-lg);
  }

  .photo-caption {
    border: none;
    padding: 0;
    font-family: var(--font-family-display);
    font-style: italic;
    font-size: var(--f2);
    color: hsl(var(--headingH) var(--headingS) var(--headingL));
    background: none;
  }

  .photo-caption::placeholder {
    color: hsl(var(--secondaryH) var(--secondaryS) var(--secondaryL));
    opacity: 1;
  }

  .photo-caption:focus {
    outline: none;
  }

  /* ── Tag editor ────────────────────────────────────────────────────── */
  .tag-editor {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s2);
  }

  .tag-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--s1);
    padding: var(--s1) var(--s2) var(--s1) var(--s3);
    border-radius: var(--br-full);
    background: var(--surface2);
    font-family: var(--font-family-mono);
    font-size: var(--f6);
    color: hsl(var(--bodyH) var(--bodyS) var(--bodyL));
  }

  .tag-remove {
    border: none;
    background: none;
    color: hsl(var(--secondaryH) var(--secondaryS) var(--secondaryL));
    cursor: pointer;
    line-height: 1;
    padding: var(--s1);
    font-size: var(--f5);
  }

  .tag-remove:hover {
    color: hsl(var(--errorH) var(--errorS) var(--errorL));
  }

  .tag-add {
    display: inline-flex;
    gap: var(--s1);
    margin: 0;
  }

  .tag-add input {
    border: 1px dashed hsl(var(--borderH) var(--borderS) var(--borderL));
    border-radius: var(--br-full);
    padding: var(--s1) var(--s3);
    font-family: var(--font-family-mono);
    font-size: var(--f6);
    background: none;
    color: inherit;
    margin: 0;
  }

  .tag-add input:focus {
    outline: none;
    border-style: solid;
    border-color: hsl(var(--brand-primaryH) var(--brand-primaryS)
      var(--brand-primaryL));
  }

  .tag-add button {
    border: none;
    background: none;
    color: hsl(var(--brand-primaryH) var(--brand-primaryS)
      var(--brand-primaryL));
    cursor: pointer;
    font-size: var(--f3);
    padding: 0 var(--s2);
  }

  /* ── EXIF readout ──────────────────────────────────────────────────── */
  /* No more <details>/<summary> — this only renders once `.photo-meta` is
     already expanded, so there's no other state for it to disclose from. */
  .exif-panel {
    padding: var(--s3);
    background: var(--surface);
    border-radius: var(--br-lg);
  }

  .exif-line {
    margin: 0 0 var(--s3);
    font-family: var(--font-family-mono);
    font-size: var(--f5);
    color: hsl(var(--bodyH) var(--bodyS) var(--bodyL));
  }

  .exif-line:last-of-type {
    margin-bottom: 0;
  }

  .exif-panel dl {
    margin: var(--s3) 0 0;
    font-family: var(--font-family-mono);
    font-size: var(--f6);
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--s2) var(--s3);
  }

  .exif-panel dt {
    color: hsl(var(--secondaryH) var(--secondaryS) var(--secondaryL));
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }

  .exif-panel dd {
    margin: 0;
    color: hsl(var(--bodyH) var(--bodyS) var(--bodyL));
  }

  .exif-panel a {
    color: hsl(var(--brand-primaryH) var(--brand-primaryS)
      var(--brand-primaryL));
  }

  /* ── Public shared-photo view ──────────────────────────────────────── */
  .shared-photo {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s3);
  }

  .shared-photo .photo-full {
    max-height: 85vh;
    cursor: default;
    border-radius: var(--br-base);
  }

  .shared-photo .photo-caption {
    font-size: var(--f3);
    text-align: center;
    padding: 0 var(--s3);
  }

  /* ── Settings toggles ──────────────────────────────────────────────── */
  .settings-toggle-label {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s3);
    padding: var(--s3);
    background: var(--surface);
    border-radius: var(--br-lg);
    cursor: pointer;
  }

  /* ── Dialogs (bulk tag editor, share) ─────────────────────────────── */
  dialog {
    background: var(--surface);
    color: hsl(var(--bodyH) var(--bodyS) var(--bodyL));
  }

  .tag-dialog {
    padding: var(--s4);
    display: flex;
    flex-direction: column;
    gap: var(--s3);
  }

  .tag-dialog h2 {
    margin: 0;
    font-size: var(--f2);
  }

  .tag-dialog-option {
    display: flex;
    align-items: center;
    gap: var(--s2);
    font-size: var(--f5);
  }

  .tag-dialog-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: var(--s2);
  }
}
