@layer components { /* Column container /* ------------------------------------------------------------------------ */ .card-columns { --bubble-size: 3.5rem; --cards-gap: min(1.2cqi, 1.7rem); --column-gap: 8px; --column-width-collapsed: 40px; --column-width-expanded: 450px; --column-transition: 200ms ease-out; --progress-increment: var(--progress-max-height) / var(--progress-max-cards); --progress-max-cards: 20; --progress-max-height: 50dvh; align-items: stretch; container-type: inline-size; display: grid; gap: var(--column-gap); grid-template-columns: 1fr var(--column-width-expanded) 1fr; justify-content: center; margin: var(--cards-gap) auto 0; max-inline-size: var(--main-width); position: relative; &:has(.card-columns__left .cards:not(.is-collapsed), .card-columns__right .cards:not(.is-collapsed)) { grid-template-columns: auto auto auto; } &:has(.cards) { min-block-size: 20lh; } @media (max-width: 639px) { --bubble-size: 3rem; } } .card-columns__left, .card-columns__right { align-items: stretch; display: flex; gap: var(--column-gap); } .card-columns__left { justify-content: end; } .card-columns__right { justify-content: start; } /* Column /* ------------------------------------------------------------------------ */ .cards { --column-color: color-mix(in srgb, var(--card-color) 15%, var(--color-canvas)); align-items: stretch; display: flex; flex-direction: column; gap: var(--cards-gap); justify-content: start; max-inline-size: var(--column-width-expanded); min-inline-size: var(--column-width-expanded); position: relative; scroll-snap-align: start; transition: var(--column-transition); /* Make sure filter dialogs don't end up behind sticky headers */ &:has([open]) { z-index: 3; } &.is-collapsed { border-radius: calc(var(--column-width-collapsed) / 2); flex: 0 0 var(--column-width-collapsed); inline-size: var(--column-width-collapsed); min-inline-size: 0; .blank-slate, .pagination-link, .card { display: none; } &:not(.cards--considering) { margin-block-start: var(--column-width-collapsed); } } &:not(.is-collapsed) { padding-inline: calc(var(--column-gap) * 2); } .bubble { inset-inline-start: 100%; translate: -90% -40%; } @media (any-hover: hover) { .card:has(.card__background img:not([src=""])):hover .card__background img:not([src=""]) { filter: blur(3px) brightness(1.2); opacity: 0.2; } } .card__steps { display: flex; } } .cards__new-column { margin-block-start: var(--column-width-collapsed); } /* Used when filtering */ .cards--grid { --cards-gap: 1rem; --card-grid-columns: 1; container-type: inline-size; flex-direction: row; flex-wrap: wrap; justify-content: center; margin-inline: auto; max-inline-size: var(--main-width); @media (min-width: 640px) { --card-grid-columns: 2; } @media (min-width: 960px) { --card-grid-columns: 3; } .card { inline-size: calc((100% - var(--cards-gap) * (var(--card-grid-columns) - 1) ) / var(--card-grid-columns)); } } /* Column Elements /* ------------------------------------------------------------------------ */ .cards__expander { align-items: center; border-radius: 99rem; cursor: pointer; display: flex; flex-direction: row-reverse; font-size: var(--text-x-small); font-weight: 600; gap: 0.5ch; position: relative; text-transform: uppercase; @media (any-hover: hover) { &:hover { filter: brightness(0.9); } } .cards.is-collapsed & { block-size: 100%; flex-direction: column; inline-size: var(--column-width-collapsed); justify-content: start; letter-spacing: 0.05em; /* Guitar string */ &:before { background-color: var(--column-color); block-size: 100%; content: ""; inline-size: 1px; inset: 0 auto; position: absolute; z-index: -2; } /* Progress */ &:after { background: linear-gradient(to bottom, var(--card-color), var(--column-color) 80%); block-size: calc(var(--column-width-collapsed) + var(--card-count) * var(--progress-increment)); border-radius: 99rem; content: ""; inline-size: 100%; inset: 0 0 auto; max-block-size: var(--progress-max-height); min-block-size: var(--column-width-collapsed); position: absolute; transition: block-size 500ms var(--ease-out-overshoot); z-index: -1; } } .cards:not(.is-collapsed) & { inline-size: 100%; margin-block-end: calc(-0.5 * var(--cards-gap)); justify-content: center; } .cards:is(.cards--considering) &:hover { cursor: unset; filter: none; } @media (any-hover: hover) { .btn--circle, ~ .btn--circle, ~ .cards__expander-menu .btn--circle { transition: opacity 300ms ease-in-out; opacity: 0; .cards:hover & { opacity: 1; } } } } .btn.cards__expander-button { --btn-background: transparent; block-size: var(--column-width-collapsed); inline-size: var(--column-width-collapsed); inset: 0 0 auto auto; position: absolute; translate: calc(var(--column-gap) * -2); z-index: var(--z-popup); .cards--considering & { translate: none; } .cards.is-collapsed & { display: none; } } .cards__expander-count { line-height: var(--column-width-collapsed); inline-size: var(--column-width-collapsed); .cards:not(.is-collapsed) & { display: none; } } .cards__expander-title { font-weight: inherit; font-size: inherit; line-height: var(--column-width-collapsed); .cards.is-collapsed & { writing-mode: vertical-rl; } .cards:not(.is-collapsed) & { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } } .cards__expander-menu { inset: 0 auto auto 0; position: absolute; translate: calc(var(--column-gap) * 2); z-index: var(--z-popup); .btn--circle { --btn-background: transparent; block-size: var(--column-width-collapsed); inline-size: var(--column-width-collapsed); } .panel { --panel-padding: 1ch; } .cards.is-collapsed & { display: none; } } .blank-slate--card { box-shadow: none !important; color: color-mix(in srgb, var(--card-color) 70%, var(--color-canvas)); p { font-size: var(--text-small); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; &.blank-slate-for-grid { display: none; .cards--grid & { display: initial; } } .cards--grid &:not(.blank-slate-for-grid) { display: none; } } } /* TODO: I think this is legacy now? */ .cards__heading { display: flex; font-size: var(--text-medium); inset-block-start: 0; justify-content: center; margin-block-start: 1px; margin-inline: -8px; /* enough to cover card shadows, but avoid overlapping bubbles */ padding-block: var(--cards-gap) 0; position: sticky; z-index: 3; /* Cover bubbles and cards on small viewports */ @media (max-width: 639px) { &:not(.cards--closed &) { margin-inline: calc(-1 * var(--cards-gap) - var(--main-padding)); } } &, .cards__filter { font-weight: bold; text-transform: uppercase; } .cards__filter { --filter-block-padding: 0.5rem; background-color: var(--color-canvas); border-radius: 99rem; inline-size: auto; margin-block: calc(-1 * var(--filter-block-padding)); padding-block: var(--filter-block-padding); } dialog { font-weight: normal; text-transform: none; } } /* Override card styles within columns /* ------------------------------------------------------------------------ */ .cards { .card { --block-space: 1em; --block-space-half: 0.5em; --card-padding-inline: 1em; --text-xx-large: 1.6em; --text-x-small: 1em; /* Set lower limit for font size */ font-size: clamp(0.6rem, 0.85cqi, 100px); } .card__tags { gap: calc(var(--card-header-space) / 2); } .card__title { line-height: 1.2; pointer-events: none; } .card__link { z-index: 1; } .card__stages, .card__hide-on-index { display: none; } .card__body { padding-block: calc(var(--card-padding-block) * 0.75) var(--card-padding-block); } .card__meta { font-weight: 600; strong, .local-time-value { font-weight: inherit; } } .card:has(.card__background img:not([src=""])) { .card__content, .card__meta, .workflow-stage:not(.workflow-stage--current) { opacity: 0; transition: opacity 0.2s ease-in-out; @media (any-hover: hover) { .card:hover & { opacity: 1; } } } } .bubble { inset-inline-start: 100%; translate: -90% -40%; } @media (any-hover: hover) { .card:has(.card__background img:not([src=""])):hover .card__background img:not([src=""]) { filter: blur(3px) brightness(1.2); opacity: 0.2; } } .card__steps { display: flex; } } /* Considering /* ------------------------------------------------------------------------ */ .cards--considering { --gradient-opacity: 25%; --bottom-gradient-size: 4em; padding-bottom: var(--bottom-gradient-size); position: relative; @supports(mask: linear-gradient(black)) { &:before { background-image: linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--color-considering) var(--gradient-opacity), transparent) 33%, color-mix(in srgb, var(--color-considering) var(--gradient-opacity), transparent) 66%, transparent 100%); content: ""; inset: calc(var(--column-width-collapsed) + var(--block-space-half)) 0 0 0; position: absolute; z-index: 0; } &:after { background: linear-gradient(90deg, color-mix(in oklch, var(--color-considering) 0%, transparent) 0%, color-mix(in oklch, var(--color-considering) 20%, transparent) 25%, color-mix(in oklch, var(--color-considering) 20%, transparent) 50%, color-mix(in oklch, var(--color-considering) 0%, transparent) 100%); content: ""; inset: calc(var(--column-width-collapsed) + var(--block-space-half)) 0 0 0; mask: var(--wavy-background-mask); position: absolute; z-index: -1; } } @media (min-width: 640px) { padding-inline: var(--cards-gap); } @media (prefers-color-scheme: dark) { --gradient-opacity: 10%; } .cards__decoration { --gradient-opacity: 30%; --size: 2.2em; background-color: var(--color-canvas); background-image: radial-gradient(ellipse at bottom, color-mix(in srgb, var(--color-considering) var(--gradient-opacity), transparent) 0%, transparent 70%); block-size: var(--size); inline-size: 100%; inset: calc(var(--column-width-collapsed) + var(--block-space) - var(--size)) 0 auto 0; position: absolute; z-index: -1; @media (prefers-color-scheme: dark) { --gradient-opacity: 15%; } @supports(mask: radial-gradient(black)) { --gradient-opacity: 30%; &:before { background: radial-gradient(ellipse at bottom, color-mix(in srgb, var(--color-considering) var(--gradient-opacity), transparent) 0%, transparent 70%); content: ""; inset: 0; mask: radial-gradient(6px at 50% calc(100% + 3px), transparent calc(99% - 2px), black calc(101% - 2px) 99%, transparent 101%) calc(50% - 8px) calc(50% - 3px + .5px)/16px 6px, radial-gradient(6px at 50% -3px, transparent calc(99% - 2px), black calc(101% - 2px) 99%, transparent 101%) 50% calc(50% + 3px)/16px 6px; position: absolute; z-index: 0; } } } .cards__decoration-end { background: linear-gradient( transparent 0%, var(--color-canvas) 90%); block-size: var(--bottom-gradient-size); content: ""; inset: auto 0 0; position: absolute; z-index: 1; } .card { --avatar-size: 2.75em; --text-small: 1.1em; background-color: var(--color-canvas); line-height: 1.2; z-index: 2; @media (min-width: 640px) { --text-xx-large: 1.6em; } } .card__collection { background-color: transparent; color: var(--card-content-color); } .card__header { color: var(--color-ink); padding-block-start: calc(var(--card-padding-block) / 2); } .card__tags { color: inherit; } .card__body { padding-block: 0 var(--card-padding-block); } .card--drafted { --card-color: var(--color-ink-medium) !important; border-color: var(--card-color) !important; border-style: dashed !important; box-shadow: none !important; } .card__people-label { display: none; } .card__title { min-block-size: 0; } } /* Collection tools /* -------------------------------------------------------------------------- */ .collection-tools.card { --border-color: var(--color-selected-dark); --border-size: 1px; --card-padding-block: var(--block-space); border: 1px solid var(--border-color); text-align: center; .separator--horizontal { margin-block: var(--block-space); } .btn--link { font-size: 1.2em; } .btn:not(.btn--link, .btn--circle) { border: 0; color: var(--color-link); } footer { font-size: var(--text-x-small); margin-block-end: calc(var(--block-space-half) * -1); } .overflow-count { font-size: 1.2em; font-weight: 500; padding: 0.5em 0.3em; } } .collection-tools__watching { display: flex; gap: 0.5ch; inline-size: 100%; margin-block: var(--block-space-half); overflow: hidden; place-content: center; position: relative; &:before, &:after { aspect-ratio: 0.5; background: linear-gradient(to right, var(--color-canvas), transparent); content: ""; inset-block: 0; position: absolute; z-index: 1; } &:before { inset-inline-start: 0; } &:after { inset-inline-end: 0; rotate: 180deg; } } /* On Deck (Not Now) /* ------------------------------------------------------------------------ */ .cards--on-deck { --card-color: var(--color-ink-light) !important; .card { --card-color: var(--color-card-complete) !important; } .bubble { display: none !important; } } /* Doing /* -------------------------------------------------------------------------- */ /* Surface a mini bubble if there are cards with bubbles inside */ .cards--doing.is-collapsed:has(.bubble:not([hidden])) { --bubble-color: var(--card-color, oklch(var(--lch-blue-medium))); --bubble-shape: 54% 46% 61% 39% / 57% 49% 51% 43%; &:before { background: radial-gradient( color-mix(in srgb, var(--bubble-color) 8%, var(--color-canvas)) 50%, color-mix(in srgb, var(--bubble-color) 48%, var(--color-canvas)) 100% ); block-size: 1em; border-radius: var(--bubble-shape); content: ""; inline-size: 1em; inset: 0 0 auto auto; position: absolute; translate: 25% -25%; z-index: 1; } } }