/* =====================================================================
   📓 Journal App
   Dash's photo journal, one entry per page. Unlike css/welcome.css this file
   breaks nothing: VT323, hard black borders, flat fills, hard offset shadows,
   discrete state changes. Window size and position live in css/main.css so
   css/responsive.css can still reach them.

   ⚠️ IT DRESSES BOTH BOOKS. js/journal-view.js lays out his father's four
   pages in the `archive` folder from the same code, so every .journal-page,
   .journal-entry-* and .journal-nav rule below is on that window too. Only
   #journal itself is Dash's alone. css/notebook.css adds the two things that
   are his father's — a rule down the left margin and the cursor on the page
   that stops — both scoped to #archive-journal, and it owns all three of that
   folder's window geometries. A change here is a change to two windows.
   ===================================================================== */

/* The panel cream rather than the shared white, so the page reads as a page
   rather than as a sheet laid on the window. That is now the only reason: the
   band of window background this was also covering — the ~11px every
   fixed-height window used to expose below .content — is gone, because
   css/main.css pins the title bar and subtracts the same number. Keeping the
   cream anyway, because the carousel sits at the bottom and nothing in
   .journal-nav paints a background of its own. Scoped by id the way css/calculator.css scopes
   its own surface, because the shared `.window .content` rule in css/main.css
   is a two-class selector and would otherwise keep its white background over a
   bare class here. Both desktop themes still win from
   `body.<theme> .window .content`, which is !important. */
#journal .content {
  display: flex;
  flex-direction: column;
  padding: 0;
  background: var(--panel);
}

/* --- Pages ---
   The flex child that absorbs the difference between a short entry and a long
   one. Because #journal has a fixed height and .content is a column, this is
   the only thing that can change size when a page turns — so the window never
   does. A page taller than the region scrolls inside it.

   scrollbar-gutter keeps that scrollbar's width reserved on platforms that
   take space for one, so a short page and a long page render the photograph at
   the same width and turning a page does not nudge the layout sideways. */
.journal-pages {
  flex: 1 1 auto;
  padding: 18px;
  overflow-y: auto;
  scrollbar-gutter: stable;
}

/* The same drawn scrollbar .msg-transcript uses in css/messages.css, mirrored
   rather than shared so neither app can move the other's furniture. It matters
   more here than it does there: most pages are taller than the region, and
   macOS hides its overlay scrollbar until you already scroll — which is how a
   page that continues below the fold ends up looking like a page that stops.
   Drawing the track always means the bar is part of the page rather than a
   surprise on the long ones. css/matrix.css and css/devil.css recolour it. */
.journal-pages::-webkit-scrollbar {
  width: 13px;
}

.journal-pages::-webkit-scrollbar-track {
  border: 2px solid #000;
  background: #ececec;
}

.journal-pages::-webkit-scrollbar-thumb {
  border: 2px solid #000;
  background: #9a9a9a;
}

/* Focusable so the arrow keys keep working after a control disables itself at
   the end of the set, but never ringed — the reader did not ask for focus, the
   carousel handed it over. */
.journal-pages:focus {
  outline: none;
}

.journal-page {
  display: none;
  /* Caps the measure when the window is maximized. Without it a 1440px window
     runs the prose to about 160 characters a line and upscales a 1024px
     photograph to fill the width; with it the page keeps its shape and sits in
     the middle of the desk. Wider than the 478px the default window gives, so
     it changes nothing at that size. */
  max-width: 640px;
  margin-inline: auto;
}

.journal-page.is-current {
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* Fills the region so a short page can distribute itself down it rather than
     hanging from the top. Resolves against the scroller's content box, which is
     its visible height less the padding. */
  min-height: 100%;
}

/* --- Entry header --- */

.journal-entry-head {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.journal-entry-title {
  margin: 0;
  font-family: "VT323", monospace;
  font-size: 25px;
  line-height: 1.1;
}

/* The date and the job share one quiet line under the title. Both recede on
   opacity rather than on a colour of their own, so they stay legible once a
   theme repaints the panel, and neither competes with the title above. */
.journal-entry-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 2px 14px;
  font-family: "VT323", monospace;
  font-size: 16px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  opacity: 0.6;
}

/* VT323 rather than Pixelify Sans, which numerals never use. */
.journal-entry-date {
  flex-shrink: 0;
}

/* Names the job, or "Day off" on the one page where there was not one. */
.journal-entry-tag {
  text-align: right;
}

.journal-entry-body {
  margin: 0;
  font-family: "VT323", monospace;
  font-size: 20px;
  line-height: 1.35;
}

/* Paragraphs are separate elements rather than blank lines in one block, so the
   gap is typographic rather than an empty row of text. Slightly tighter than
   the page's own 10px gap, which keeps the prose reading as one passage while
   still separating it from the photograph above. */
.journal-entry-body + .journal-entry-body {
  margin-top: -2px;
}

/* --- A page PURGE has been through ---
   Stage one of the collapse empties every container in the machine, and
   createEmptiedJournalPage() in js/journal-view.js keeps each entry's head and
   puts this one line where the writing was. Only Dash's book can reach it: the
   archive is shut for the whole of the collapse. It carries .journal-entry-body as
   well, so it inherits that rule's face, size and leading and lands in exactly
   the position the first paragraph occupied — the point is that the page is
   unchanged apart from being empty.

   Recedes on opacity rather than on a grey of its own, the same reasoning as
   .journal-entry-meta: css/devil.css repaints this panel and a hardcoded #555
   would either vanish into it or refuse to follow it. Fainter than the meta
   line's 0.6, so the surviving label reads as the louder of the two. */
.journal-entry-empty {
  opacity: 0.55;
}

/* --- Text pages ---
   An entry with no photograph is a short block of prose in a region built for a
   picture, so it would otherwise hang from the top with a third of the page
   empty below it. No page in Dash's book takes this branch — every entry in
   js/apps/journal.js carries a photograph — but every page in the archive does,
   because his father never had a camera, so this is the treatment his whole
   journal is set in and not a spare. css/notebook.css used to hand-copy the
   three values below for exactly that window.

   Three things fix the stranded block, and none of them is padding the writing
   out to fill a box:

     1. the block is centred in the space rather than pinned to the top;
     2. the type goes up two points with more leading, which is the difference
        between a stranded caption and a page someone meant to set;
     3. the measure narrows, so the longer line height does not produce lines
        too wide to track back from.

   `safe center` is what makes the centring survive a page that grows past the
   region — plain `center` would push the first line out of reach above the
   scroll origin. Browsers that do not know the keyword drop the declaration and
   fall back to the top, which is the same thing the overflow case wants. */

.journal-page.is-textonly {
  justify-content: safe center;
  gap: 14px;
  max-width: 560px;
}

.journal-page.is-textonly .journal-entry-body {
  font-size: 22px;
  line-height: 1.5;
}

.journal-page.is-textonly .journal-entry-body + .journal-entry-body {
  margin-top: 0;
}

/* The header is part of the centred block rather than a heading above it, so it
   needs a little more air beneath it once the body opens up. */
.journal-page.is-textonly .journal-entry-head {
  margin-bottom: 2px;
}

/* --- Photos ---
   Framed the way Finder frames a leaf image in .finder-icon img.finder-thumb:
   the same 3px black border over the same hard offset shadow, mirrored here
   rather than borrowed so neither app can move the other's furniture. The one
   value deliberately not carried over is object-fit: cover — Finder crops
   square so a grid lines up, while these are photographs and keep their own
   aspect ratios. */

.journal-photo-frame {
  display: block;
  width: 100%;
  border: 3px solid #000;
  background: #fff;
  box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.35);
  cursor: pointer;
  line-height: 0;
}

.journal-photo-frame:hover,
.journal-photo-frame:focus-visible {
  box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.9);
  outline: none;
}

/* Positional, like .finder-toggle-btn's press state. Growth and shrink stay
   out of ordinary controls. */
.journal-photo-frame:active {
  box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.9);
  transform: translate(2px, 2px);
}

.journal-photo {
  display: block;
  width: 100%;
  /* The width and height attributes in js/apps/journal.js carry the intrinsic
     size, so the browser reserves the right box before the file arrives and
     the page never reflows as the photograph decodes. */
  height: auto;
}

/* --- Carousel ---
   Real <button> elements, unlike the photo frame above and unlike the welcome
   card. These are ordinary controls and should be dressed like every other
   button in the OS, so being repainted by css/matrix.css and css/devil.css is
   the point rather than the hazard. It also means `disabled` is real: at the
   ends the controls do not respond, instead of looking spent while still
   firing. */

.journal-nav {
  position: relative;
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 18px 12px;
}

.journal-nav::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  height: 3px;
  background: currentColor;
  opacity: 0.85;
}

/* The .wp-arrow idiom from css/settings.css, which is the OS's existing
   prev/next carousel, scaled up from a thumbnail stepper to a primary control. */
.journal-nav-btn {
  flex-shrink: 0;
  padding: 6px 13px;
  border: 3px solid #000;
  background: #e0e0e0;
  box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.9);
  font-family: "VT323", monospace;
  font-size: 18px;
  line-height: 1;
  letter-spacing: 1px;
  color: #000;
  cursor: pointer;
}

/* Travels into its own shadow when pressed, the same idiom as .wp-arrow. */
.journal-nav-btn:not(:disabled):active {
  transform: translate(3px, 3px);
  box-shadow: none;
}

/* No !important anywhere here, so this still reads as spent once a theme has
   repainted the fill and the border underneath it. */
.journal-nav-btn:disabled {
  opacity: 0.35;
  box-shadow: none;
  transform: translate(3px, 3px);
  cursor: not-allowed;
}

/* Numerals, so VT323 and never Pixelify Sans. Counting rather than dots
   because the set is still growing: "3 / 4" costs the same room at forty
   entries as it does at four. */
.journal-nav-count {
  font-family: "VT323", monospace;
  font-size: 20px;
  letter-spacing: 1px;
  opacity: 0.75;
}

/* --- Phone --- */

@media (max-width: 600px) {
  .journal-pages {
    padding: 14px;
  }

  /* At this width the date and the job cannot share a line without one of them
     wrapping mid-word. */
  .journal-entry-meta {
    flex-direction: column;
    align-items: flex-start;
  }

  .journal-entry-tag {
    text-align: left;
  }

  .journal-nav {
    padding: 10px 14px 11px;
  }

  .journal-nav-btn {
    padding: 6px 10px;
    font-size: 17px;
  }
}
