Compare commits

...

14 commits

10 changed files with 112 additions and 81 deletions

View file

@ -16,18 +16,11 @@ MAKEPAGES := $(TMPDIR)/make-pages
YAMLS != find -L $(DATADIR) -name $(INFONAME) YAMLS != find -L $(DATADIR) -name $(INFONAME)
TSCRIPTS != find script -name '*.ts' TSCRIPTS != find script -name '*.ts'
STYLES != find style -name '*.css' STYLES != find style -type f
STYLESVGS != find style -name '*.svg' FONTS != find fonts -type f
STYLEPNGS != find style -name '*.png'
STATIC = $(STYLES) $(FONTS)
FONTS != find fonts \
-iname '*.eot' -or -iname '*.svg' -or \
-iname '*.ttf' -or -iname '*.woff' -or \
-iname '*.woff2' -or -iname '*.css'
STATIC = $(STYLES) $(STYLEPNGS) $(STYLESVGS) $(FONTS)
BSTATIC = $(patsubst %,$(BUILDDIR)/%,$(STATIC)) BSTATIC = $(patsubst %,$(BUILDDIR)/%,$(STATIC))
BSCRIPTS = $(patsubst %.ts,$(BUILDDIR)/%.js,$(TSCRIPTS)) BSCRIPTS = $(patsubst %.ts,$(BUILDDIR)/%.js,$(TSCRIPTS))

View file

@ -18,9 +18,15 @@ import Data.List.NonEmpty (NonEmpty, toList)
data Chunk = Lit String | Var String data Chunk = Lit String | Var String
-- |
-- * use @$var@ to insert a variable (instance of 'CanBuild')
-- * use @$&@ to insert nothing like @\&@ in a string (e.g. to add whitespace
-- at the start or end, or to have a variable followed by a letter
-- * use @$$@ for a literal @$@
parseB :: String -> ExpQ parseB :: String -> ExpQ
parseB = toExpQ . reverse . go "" [] . trim where parseB = toExpQ . reverse . go "" [] . trim where
trim = dropWhileEnd isSpace . dropWhile (== '\n') trim = dropWhileEnd isSpace . dropWhile isSpace
go acc cs [] = addLit acc cs go acc cs [] = addLit acc cs
go acc cs ('$':'&':rest) = go acc cs rest -- $&: expands to nothing go acc cs ('$':'&':rest) = go acc cs rest -- $&: expands to nothing
go acc cs ('$':'$':rest) = go ('$' : acc) cs rest -- $$: expands to one $ go acc cs ('$':'$':rest) = go ('$' : acc) cs rest -- $$: expands to one $
@ -58,7 +64,8 @@ escId = foldMap esc1 . Strict.unpack where
escAttr :: Strict.Text -> Builder escAttr :: Strict.Text -> Builder
escAttr = foldMap esc1 . Strict.unpack where escAttr = foldMap esc1 . Strict.unpack where
esc1 c = fromMaybe (singleton c) $ lookup c esc1 c = fromMaybe (singleton c) $ lookup c
[('<', "&lt;"), ('>', "&gt;"), ('"', "&quot;"), ('\'', "&apos;")] [('<', "&lt;"), ('>', "&gt;"), ('"', "&quot;"), ('\'', "&apos;"),
('&', "&amp;")]
class CanBuild a where build :: a -> Builder class CanBuild a where build :: a -> Builder

View file

@ -80,9 +80,7 @@ make' root (GalleryInfo {title, desc, prefix, filters, hidden}) infos = [b|
</nav> </nav>
<main> <main>
<ul class=grid> $items
$items
</ul>
</main> </main>
</div> </div>
|] |]
@ -129,16 +127,17 @@ makeFilter prefix initial tag count = [b|
where where
id' = [b|$prefix$&_$tag'|] id' = [b|$prefix$&_$tag'|]
tag' = escId tag tag' = escId tag
checked = if HashSet.member tag initial then [b| checked|] else "" checked = if HashSet.member tag initial then [b|$& checked|] else ""
hidden = if count <= 1 then [b| hidden|] else "" hidden = if count <= 1 then [b|$& hidden|] else ""
makeYearItems :: Bool -- ^ nsfw makeYearItems :: Bool -- ^ nsfw
-> Int -- ^ year -> Int -- ^ year
-> [(FilePath, Info)] -> [(FilePath, Info)]
-> Builder -> Builder
makeYearItems nsfw year infos = [b| makeYearItems nsfw year infos = [b|
<li class="item year-marker" id="marker-$year"> <h2 class="item year-marker" id="marker-$year" aria-label=$year>
<span class=year-text>$year'</span> $year'
</h2>
$items $items
|] |]
where where
@ -147,24 +146,25 @@ makeYearItems nsfw year infos = [b|
makeItem :: Bool -> FilePath -> Info -> Builder makeItem :: Bool -> FilePath -> Info -> Builder
makeItem nsfw file info@(Info {bg}) = [b| makeItem nsfw file info@(Info {bg}) = [b|
<li class="item post$nsfw'" data-year=$year' data-updated="$updated'" <figure class="item post$nsfw'" data-year=$year' data-updated="$updated'"
data-tags="$tags'"> data-tags="$tags'">
<a href="$dir"> <a href="$dir">
<img src="$thumbnail" loading=lazy$bgStyle <img src="$thumbnail" loading=lazy$bgStyle
width=200 height=200 width=200 height=200
title="$tooltip"> alt="$title" title="$tooltip">
</a> </a>
</figure>
|] |]
where where
title = fromMaybe info.title $ info.galleryTitle title = escAttr $ fromMaybe info.title info.galleryTitle
dir = takeDirectory file dir = takeDirectory file
thumbnail = getThumb dir info thumbnail = getThumb dir info
nsfw' = if nsfw && anyNsfw info then [b| nsfw|] else "" nsfw' = if nsfw && anyNsfw info then [b|$& nsfw|] else ""
tags' = fold $ intersperse ";" $ map fromText $ tagsFor nsfw info tags' = fold $ intersperse ";" $ map fromText $ tagsFor nsfw info
date = latestDateFor nsfw info date = latestDateFor nsfw info
date' = formatTooltip date date' = formatTooltip date
year' = date.year year' = date.year
updated' = if hasUpdatesFor nsfw info then [b|true|] else [b|false|] updated' = if hasUpdatesFor nsfw info then [b|true|] else [b|false|]
bgStyle = case bg of Other col -> [b| style="background: $col"|]; _ -> "" bgStyle = case bg of Other col -> [b|$& style="background: $col"|]; _ -> ""
tooltip = [b|$title ($upd$date')|] tooltip = [b|$title ($upd$date')|]
where upd = if hasUpdatesFor nsfw info then "updated " else "" :: Builder where upd = if hasUpdatesFor nsfw info then "updated " else "" :: Builder

View file

@ -74,13 +74,13 @@ makeItem :: GalleryInfo -> Builder
makeItem (GalleryInfo {title, desc, prefix, filters}) = [b| makeItem (GalleryInfo {title, desc, prefix, filters}) = [b|
<li$nsfw><a href=$prefix title="$desc">$title</a></li> <li$nsfw><a href=$prefix title="$desc">$title</a></li>
|] |]
where nsfw = if hasNsfw filters then [b| class=nsfw|] else "" where nsfw = if hasNsfw filters then [b|$& class=nsfw|] else ""
makeLink :: Link -> Builder makeLink :: Link -> Builder
makeLink (Link {title, url, nsfw}) = [b| makeLink (Link {title, url, nsfw}) = [b|
<li$nsfw'><a href=$url>$title</a> <li$nsfw'><a href=$url>$title</a>
|] |]
where nsfw' = if nsfw then [b| class=nsfw|] else "" where nsfw' = if nsfw then [b|$& class=nsfw|] else ""
hasNsfw :: GalleryFilters -> Bool hasNsfw :: GalleryFilters -> Bool
hasNsfw (GalleryFilters {nsfw}) = nsfw /= NoNsfw hasNsfw (GalleryFilters {nsfw}) = nsfw /= NoNsfw

View file

@ -105,6 +105,7 @@ data Image =
label :: !Text, label :: !Text,
path :: !FilePath, path :: !FilePath,
download :: !(Maybe FilePath), download :: !(Maybe FilePath),
desc :: !Text,
nsfw :: !Bool, nsfw :: !Bool,
warning :: !(Maybe Text), warning :: !(Maybe Text),
resize :: !Bool resize :: !Bool
@ -198,7 +199,7 @@ thumb (Info {thumb', images}) =
latestDateFor :: Bool -> Info -> Date latestDateFor :: Bool -> Info -> Date
latestDateFor nsfw i = maximum $ i.date : mapMaybe relDate (updatesFor nsfw i) latestDateFor nsfw i = maximum $ i.date : mapMaybe relDate (updatesFor nsfw i)
where where
relDate (date, us) = date <$ guard (not $ null us || any (.ignoreSort) us) relDate (date, us) = date <$ guard (not $ null us || all (.ignoreSort) us)
latestYearFor :: Bool -> Info -> Int latestYearFor :: Bool -> Info -> Int
latestYearFor nsfw info = (latestDateFor nsfw info).year latestYearFor nsfw info = (latestDateFor nsfw info).year
@ -369,17 +370,18 @@ unlabelledImage' label' y = asStr y <|> asObj y
where where
asStr = YAML.withStr "path" \(Text.unpack -> path) -> asStr = YAML.withStr "path" \(Text.unpack -> path) ->
let label = fromMaybe (pathToLabel path) label' in let label = fromMaybe (pathToLabel path) label' in
pure $ Image {label, path, download = Nothing, pure $ Image {label, path, download = Nothing, desc = "",
nsfw = False, warning = Nothing, resize = True} nsfw = False, warning = Nothing, resize = True}
asObj = YAML.withMap "image info" \m -> do asObj = YAML.withMap "image info" \m -> do
checkKeys m ["path", "download", "nsfw", "warning", "resize"] checkKeys m ["path", "download", "desc", "nsfw", "warning", "resize"]
path <- m .: "path" path <- m .: "path"
download <- m .:? "download" download <- m .:? "download"
desc <- m .:? "desc" .!= ""
nsfw <- m .:? "nsfw" .!= False nsfw <- m .:? "nsfw" .!= False
warning <- m .:? "warning" warning <- m .:? "warning"
resize <- m .:? "resize" .!= True resize <- m .:? "resize" .!= True
let label = fromMaybe (pathToLabel path) label' let label = fromMaybe (pathToLabel path) label'
pure $ Image {label, path, download, nsfw, warning, resize} pure $ Image {label, path, download, nsfw, warning, desc, resize}
pathToLabel = Text.pack . gapToSpace . takeBaseName pathToLabel = Text.pack . gapToSpace . takeBaseName
gapToSpace = map \case '-' -> ' '; '_' -> ' '; c -> c gapToSpace = map \case '-' -> ' '; '_' -> ' '; c -> c
@ -407,14 +409,13 @@ instance FromYAML Link where
updateList :: Maybe (YAML.Node YAML.Pos) -> updateList :: Maybe (YAML.Node YAML.Pos) ->
YAML.Parser [(Date, NonEmpty Update)] YAML.Parser [(Date, NonEmpty Update)]
updateList = updateList =
maybe (pure []) $ YAML.withMap "updates" $ maybe (pure []) $ YAML.withMap "updates" $ traverse bodies . Map.toList
nonEmptys <=< traverse bodies . Map.toList
where where
bodies (date', rest) = (,) <$> parseYAML date' <*> body rest bodies (date', rest) = (,) <$> parseYAML date' <*> body rest
body b = body b = return <$> body1 b <|> YAML.withSeq "update list" (bodyN b) b
return <$> body1 b
<|> YAML.withSeq "update list" (traverse body1) b
body1 b = asDesc b <|> asObj b body1 b = asDesc b <|> asObj b
bodyN y =
maybe (YAML.typeMismatch "non-empty list" y) (traverse body1) . nonEmpty
asDesc = YAML.withStr "desc" \desc -> asDesc = YAML.withStr "desc" \desc ->
pure $ Update {desc, nsfw = False, ignoreSort = False} pure $ Update {desc, nsfw = False, ignoreSort = False}
asObj = YAML.withMap "update info" \m -> do asObj = YAML.withMap "update info" \m -> do
@ -423,8 +424,6 @@ updateList =
nsfw <- m .:? "nsfw" .!= False nsfw <- m .:? "nsfw" .!= False
ignoreSort <- m .:? "ignore-sort" .!= False ignoreSort <- m .:? "ignore-sort" .!= False
pure $ Update {desc, nsfw, ignoreSort} pure $ Update {desc, nsfw, ignoreSort}
nonEmptys = traverse $ traverse $
maybe (fail "expected non-empty list") pure . nonEmpty
data GalleryInfo = data GalleryInfo =

View file

@ -26,11 +26,12 @@ make' :: Strict.Text -> Strict.Text -> GalleryInfo
-> Maybe FilePath -> [(FilePath, Info)] -> Builder -> Maybe FilePath -> [(FilePath, Info)] -> Builder
make' root name ginfo@(GalleryInfo {title, desc, prefix}) output infos = [b| make' root name ginfo@(GalleryInfo {title, desc, prefix}) output infos = [b|
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel> <channel>
<title>$name$title</title> <title><![CDATA[$name$title]]></title>
<link>$link</link> <link>$link</link>
<description>$desc</description> <description><![CDATA[$desc]]></description>
$selflink $selflink
$items $items
@ -50,11 +51,12 @@ make' root name ginfo@(GalleryInfo {title, desc, prefix}) output infos = [b|
makeItem :: Strict.Text -> FilePath -> Bool -> FilePath -> Info -> Builder makeItem :: Strict.Text -> FilePath -> Bool -> FilePath -> Info -> Builder
makeItem root prefix nsfw path info@(Info {title}) = [b| makeItem root prefix nsfw path info@(Info {title}) = [b|
<item> <item>
<title>$title$suffix</title> <title><![CDATA[$title$suffix]]></title>
<link>$link</link> <link>$link</link>
<guid>$link</guid> <guid>$link</guid>
$body <dc:creator><![CDATA[$creator]]></dc:creator>
<pubDate>$date</pubDate> <pubDate>$date</pubDate>
$body
</item> </item>
|] |]
where where
@ -77,20 +79,37 @@ makeItem root prefix nsfw path info@(Info {title}) = [b|
dir = takeDirectory path dir = takeDirectory path
link = [b|$root/$prefix/$dir|] link = [b|$root/$prefix/$dir|]
creator = maybe "niss" (.name) info.artist
date = formatRSS $ latestDateFor nsfw info date = formatRSS $ latestDateFor nsfw info
artist = ifJust info.artist \case artist = ifJust info.artist \case
Artist name Nothing -> [b|<p>by $name|] Artist name Nothing -> [b|<p>by $name|]
Artist name (Just url) -> [b|<p>by <a href="$url">$name</a>|] Artist name (Just url) -> [b|<p>by <a href="$url">$name</a>|]
desc = makeDesc $ descFor nsfw info desc = makeDesc $ descFor nsfw info
image = case previewImage info of preview = previewImage info
Just (PFull img) -> figure $ pageFile img image = case preview of
Just (PThumb th) -> figure $ thumbFile th Just (PFull img) -> figure (escAttr img.desc) $ pageFile img
Just (PThumb th) -> figure "full image hidden" $ thumbFile th
Nothing -> "" Nothing -> ""
figure p = [b|<figure> <a href="$link"><img src="$link/$p"></a> </figure>|] msg = case preview of
Just (PThumb _) -> "<p>(full image hidden; open to see)</p>"
_ -> "" :: Text
figure alt p = [b|
<figure aria-describedby=mainimg>
<a href="$link">
<img id=mainimg src="$link/$p" alt="$alt" title="$alt">
</a>
</figure>
$msg
|]
makeDesc :: Desc -> Builder makeDesc :: Desc -> Builder
makeDesc NoDesc = "" makeDesc NoDesc = ""
makeDesc (TextDesc txt) = [b|$txt|] makeDesc (TextDesc txt) = [b|$txt|]
makeDesc (LongDesc fs) = [b|<dl>$fields</dl>|] makeDesc (LongDesc fs) = [b|<ul>$fields</ul>|] where
where fields = map (\(DescField {name, text}) -> [b|<dt>$name <dd>$text|]) fs fields = map mkField fs
mkField (DescField {name, text}) = [b|
<li> <b>$name</b>:
$text
|]

View file

@ -17,6 +17,7 @@ import qualified Data.HashSet as Set
import Data.Traversable import Data.Traversable
import Data.Semigroup import Data.Semigroup
import Data.List.NonEmpty (toList) import Data.List.NonEmpty (toList)
import Data.Char (isSpace)
-- | e.g. only nsfw images are present for a non-nsfw page -- | e.g. only nsfw images are present for a non-nsfw page
@ -95,6 +96,8 @@ make' root siteName prefix nsfw _dataDir dir
Just (Artist {name}) -> [b|by $name|] Just (Artist {name}) -> [b|by $name|]
Nothing -> "by niss" Nothing -> "by niss"
let alt = escAttr image0.desc
let updateDate = ifJust (last' updates) \(d, _) -> let updateDate = ifJust (last' updates) \(d, _) ->
let updated = formatLong d in let updated = formatLong d in
[b|<br> <span class=updated>updated $updated</span>|] [b|<br> <span class=updated>updated $updated</span>|]
@ -104,23 +107,25 @@ make' root siteName prefix nsfw _dataDir dir
let nsfwDialog = NsfwWarning.dialog nsfw' let nsfwDialog = NsfwWarning.dialog nsfw'
let imageMeta = case previewImage info of let imageMeta = case previewImage info of
Just (PFull (Image {path})) -> [b| Just (PFull (pageFile -> path)) -> [b|
<meta property=og:image content="$url/$path"> <meta property=og:image content="$url/$path">
<meta name=twitter:card content=summary_large_image> <meta name=twitter:card content=summary_large_image>
<meta name=twitter:image content="$url/$path"> <meta name=twitter:image content="$url/$path">
|] |]
Just (PThumb path) -> [b| Just (PThumb (thumbFile -> path)) -> [b|
<meta property=og:image content="$url/$path"> <meta property=og:image content="$url/$path">
<meta name=twitter:card content=summary> <meta name=twitter:card content=summary>
|] |]
Nothing -> throw $ NoThumb dir Nothing -> throw $ NoThumb dir
let escTitle = escAttr title
pure [b| pure [b|
<!DOCTYPE html> <!DOCTYPE html>
<html lang=en> <html lang=en>
<meta charset=utf-8> <meta charset=utf-8>
<meta name=viewport content="width=1200,viewport-fit=cover"> <meta name=viewport content="width=1200,viewport-fit=cover">
<link rel=stylesheet href=/style/shiny/single.css> <link rel=stylesheet href=/style/shiny/single.css blocking=render>
<link rel=icon href=/style/niss.svg> <link rel=icon href=/style/niss.svg>
<meta property=og:type content=article> <meta property=og:type content=article>
@ -138,13 +143,13 @@ make' root siteName prefix nsfw _dataDir dir
$prefetches $prefetches
<title>$title</title> <title>$escTitle</title>
$nsfwDialog $nsfwDialog
<div class=page> <div class=page>
<header> <header>
<h1>$title</h1> <h1>$escTitle</h1>
<h2 id=date class="right corner"> <h2 id=date class="right corner">
$formattedDate $updateDate $formattedDate $updateDate
</h2> </h2>
@ -156,10 +161,10 @@ make' root siteName prefix nsfw _dataDir dir
$buttonBar $buttonBar
<main> <main>
<figure id=mainfig> <figure id=mainfig aria-labelledby=mainimg>
$warning' $warning'
<a id=mainlink href="$download0" title="download full version"> <a id=mainlink href="$download0" title="download full version">
<img id=mainimg src="$path0'" alt=""> <img id=mainimg src="$path0'" alt="$alt" title="$alt">
</a> </a>
</figure> </figure>
@ -297,16 +302,17 @@ altButton :: Image -> Text -> Builder
altButton img i = [b| altButton img i = [b|
<li$nsfwClass> <li$nsfwClass>
<input type=radio name=variant id="$i" value="$path'" <input type=radio name=variant id="$i" value="$path'"
data-link="$link"$warning'> data-link="$link"$warning' data-alt="$alt">
<label for="$i"$nsfwLabelClass>$label</label> <label for="$i"$nsfwLabelClass>$label</label>
|] |]
where where
Image {label, nsfw, warning, download} = img Image {label, nsfw, warning, download} = img
nsfwClass = if nsfw then [b| class=nsfw|] else "" nsfwClass = if nsfw then [b|$& class=nsfw|] else ""
nsfwLabelClass = if nsfw then [b| class=nsfw-label|] else "" nsfwLabelClass = if nsfw then [b|$& class=nsfw-label|] else ""
path' = pageFile img path' = pageFile img
link = fromMaybe (bigFile img) download link = fromMaybe (bigFile img) download
warning' = ifJust warning \(escAttr -> w) -> [b| data-warning="$w"|] warning' = ifJust warning \(escAttr -> w) -> [b|$& data-warning="$w"|]
alt = img.desc
makeTags :: FilePath -> [Strict.Text] -> Builder makeTags :: FilePath -> [Strict.Text] -> Builder
makeTags undir tags = makeTags undir tags =
@ -361,4 +367,8 @@ makeUpdate date ups = [b|
<dd>$desc <dd>$desc
|] where |] where
date' = formatSlash date date' = formatSlash date
desc = mconcat $ map fromText $ intersperse "; " $ toList $ fmap (.desc) ups desc = mconcat $
intersperse "; " $
map (fromText . Strict.dropWhileEnd isSpace) $
toList $
fmap (.desc) ups

View file

@ -106,14 +106,18 @@ function makeFragment() {
} }
} }
type Shortcuts = { [short: string]: Set<string> }; type Shortcuts = { [short: string]: Set<string> };
const shortcuts: Shortcuts = { const shortcuts: Shortcuts = {
'summary': new Set('require_artsummary'), summary: new Set(['require_artsummary']),
'colourexamples': new Set('require_colourexample'), colourexamples: new Set(['require_colourexample']),
'flatexamples': new Set('require_flatexample'), flatexamples: new Set(['require_flatexample']),
'sketchexamples': new Set('require_sketchexample'), sketchexamples: new Set(['require_sketchexample']),
'iconexamples': new Set('require_iconexample'), iconexamples: new Set(['require_iconexample']),
'curated': new Set('require_curated') curated: new Set(['require_curated']),
gecs: new Set(['require_niss', 'require_nisse']),
qt: new Set(['require_q_t_']),
kesi: new Set(['require_kesi']),
}; };
function useFragment() { function useFragment() {
@ -195,12 +199,11 @@ function setup() {
itemsByYear = new Map; itemsByYear = new Map;
for (const item of items) { for (const item of items) {
const year = item.dataset.year; const year = item.dataset.year;
if (year !== undefined) { if (!year) continue;
if (!itemsByYear.has(year)) { if (!itemsByYear.has(year)) {
itemsByYear.set(year, new Set([item])); itemsByYear.set(year, new Set([item]));
} else { } else {
itemsByYear.get(year)?.add(item); itemsByYear.get(year)!.add(item);
}
} }
} }

View file

@ -21,7 +21,8 @@ function addCWListeners(id: string | null, caption: HTMLElement): void {
e => { if (e.key == 'Enter') openCW(id, caption, true) }); e => { if (e.key == 'Enter') openCW(id, caption, true) });
} }
function setImage(id: string, src: string, href: string, cw: string): void { function setImage(id: string, src: string, href: string,
alt: string, cw: string): void {
const curCw = document.getElementById('cw'); const curCw = document.getElementById('cw');
const coverNew = cw != '' && !opened.has(id) && !skipAll.checked; const coverNew = cw != '' && !opened.has(id) && !skipAll.checked;
@ -45,12 +46,14 @@ function setImage(id: string, src: string, href: string, cw: string): void {
// else no cover before or after // else no cover before or after
mainimg.src = src; mainimg.src = src;
mainimg.alt = mainimg.title = alt;
mainlink.href = href; mainlink.href = href;
} }
function activateButton(button: HTMLInputElement, doPush = true): void { function activateButton(button: HTMLInputElement, doPush = true): void {
setImage(button.id, button.value, setImage(button.id, button.value,
button.dataset.link!, button.dataset.link!,
button.dataset.alt ?? '',
button.dataset.warning ?? ''); button.dataset.warning ?? '');
if (doPush) history.pushState(null, '', '#' + button.id); if (doPush) history.pushState(null, '', '#' + button.id);

View file

@ -154,7 +154,7 @@
} }
.grid { main {
padding: 0; padding: 0;
display: grid; display: grid;
grid: auto-flow / repeat(auto-fit, var(--image-size)); grid: auto-flow / repeat(auto-fit, var(--image-size));
@ -169,6 +169,7 @@
width: var(--image-size); width: var(--image-size);
height: var(--image-size); height: var(--image-size);
overflow: hidden; overflow: hidden;
margin: 0;
position: relative; position: relative;
} }
@ -185,17 +186,13 @@
box-shadow: var(--focus-box); box-shadow: var(--focus-box);
} }
.year-marker { .year-marker:not([hidden]) {
/* uncomment to reenable line breaks before year markers */ /* uncomment to reenable line breaks before year markers */
/* grid-area: auto / 1; */ /* grid-area: auto / 1; */
padding: var(--border-thickness); padding: var(--border-thickness);
}
.year-text {
--gap: 0.2em;
display: grid; display: grid;
grid-template-columns: repeat(2, calc(50% - 3 * var(--gap))); grid-template-columns: repeat(2, calc(50% - 3 * var(--gap)));
grid-gap: var(--gap); grid-gap: 0;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 100%; height: 100%;