Every Monday, each rep gets one Slack message listing their Salesforce deals with no activity or stage change in two weeks, biggest first.

UsesSalesforceSlack

Nudge reps about stalled Salesforce deals

ScheduleRun every Monday at 08:00.Run every Monday at 08:00.
ValuesSet salesforceAddress to blank.Set salesforceAddress to blank.
ValuesSet daysIdle to 14.Set daysIdle to 14.
ValuesSet managerEmail to blank.Set managerEmail to blank.
ValuesSet currency to USD.Set currency to USD.
ValuesSet maxDealsPerMessage to 20.Set maxDealsPerMessage to 20.
TextTrim currency and save it as currency.Trim currency and save it as currency.
TextMake currency uppercase and save it as currency.Make currency uppercase and save it as currency.
Decisions & LoopsIf the length of currency is not 3If the length of currency is not 3
Yes
Decisions & LoopsStop and report a problem: Set 'currency' to the three-letter code of the currency your Salesforce amounts are in, such as USD, GBP or EUR.Stop and report a problem: Set 'currency' to the three-letter code of the currency your Salesforce amounts are in, such as USD, GBP or EUR.
No
No steps
TextTrim managerEmail and save it as managerEmail.Trim managerEmail and save it as managerEmail.
Decisions & LoopsIf managerEmail isn't blank and managerEmail doesn't contain @If managerEmail isn't blank and managerEmail doesn't contain @
Yes
Decisions & LoopsStop and report a problem: Set 'managerEmail' to the email address the sales manager uses in Slack, such as dana@yourcompany.com, or leave it empty to skip the manager's summary.Stop and report a problem: Set 'managerEmail' to the email address the sales manager uses in Slack, such as dana@yourcompany.com, or leave it empty to skip the manager's summary.
No
No steps
TextTrim salesforceAddress and save it as salesforceLink.Trim salesforceAddress and save it as salesforceLink.
Decisions & LoopsIf salesforceLink doesn't contain ://If salesforceLink doesn't contain ://
Yes
ValuesChange salesforceLink to https://@salesforceLink.Change salesforceLink to https://@salesforceLink.
No
No steps
TextExtract the first domain from salesforceLink and save it as salesforceHost.Extract the first domain from salesforceLink and save it as salesforceHost.
TextReplace .lightning.force.com with .my.salesforce.com in salesforceHost and save it as salesforceHost.Replace .lightning.force.com with .my.salesforce.com in salesforceHost and save it as salesforceHost.
TextReplace .my.salesforce-setup.com with .my.salesforce.com in salesforceHost and save it as salesforceHost.Replace .my.salesforce-setup.com with .my.salesforce.com in salesforceHost and save it as salesforceHost.
Decisions & LoopsIf salesforceHost doesn't end with .my.salesforce.comIf salesforceHost doesn't end with .my.salesforce.com
Yes
Decisions & LoopsStop and report a problem: '@salesforceAddress' does not look like your Salesforce address. Paste the My Domain URL you used when you connected Salesforce, such as https://acme.my.salesforce.com (in Salesforce Setup, search for My Domain to find it), into 'salesforceAddress' and run it again.Stop and report a problem: '@salesforceAddress' does not look like your Salesforce address. Paste the My Domain URL you used when you connected Salesforce, such as https://acme.my.salesforce.com (in Salesforce Setup, search for My Domain to find it), into 'salesforceAddress' and run it again.
No
No steps
Dates & TimesGet today's date and save it as today.Get today's date and save it as today.
MathSet daysBack to daysIdle multiplied by -1.Set daysBack to daysIdle multiplied by -1.
Dates & TimesMove today by daysBack days and save it as cutoffDate.Move today by daysBack days and save it as cutoffDate.
Dates & TimesGet the date 1 day after cutoffDate and save it as dayAfterCutoff.Get the date 1 day after cutoffDate and save it as dayAfterCutoff.
Dates & TimesMake dayAfterCutoff readable as “2026-11-02T14:05:00Z” and save it as stageCutoff.Make dayAfterCutoff readable as “2026-11-02T14:05:00Z” and save it as stageCutoff.
ValuesSet stalledDeals to an empty list.Set stalledDeals to an empty list.
ValuesSet afterId to blank.Set afterId to blank.
ValuesSet morePages to true.Set morePages to true.
ValuesSet pagesRead to 0.Set pagesRead to 0.
ValuesSet readCapped to false.Set readCapped to false.
Decisions & LoopsWhile morePages is yes:While morePages is yes:
ValuesSet idFilter to blank.Set idFilter to blank.
Decisions & LoopsIf afterId isn't blankIf afterId isn't blank
Yes
TextBuild the text AND Id > '@afterId' and save it as idFilter.Build the text AND Id > '@afterId' and save it as idFilter.
No
No steps
Decisions & LoopsIf a step below fails, save the error as salesforceErrorIf a step below fails, save the error as salesforceError
Try
SalesforceSalesforceRun a query. Save it as stalledPage.Run a query. Save it as stalledPage.SELECT Id, Name, Amount, StageName, CloseDate, LastActivityDate, LastStageChangeDate, CreatedDate, Owner.Name, Owner.Email, Owner.IsActive, Account.Name FROM Opportunity WHERE IsClosed = false AND (LastActivityDate = null OR LastActivityDate <= cutoffDate) AND (LastStageChangeD...
ListsCombine stalledDeals and stalledPage.records into one list and save it as stalledDeals.Combine stalledDeals and stalledPage.records into one list and save it as stalledDeals.
ValuesChange morePages to false.Change morePages to false.
Decisions & LoopsIf stalledPage.records isn't emptyIf stalledPage.records isn't empty
Yes
Decisions & LoopsIf stalledPage.done is no or the length of stalledPage.records is greater than or…If stalledPage.done is no or the length of stalledPage.records is greater than or…
Yes
ValuesChange afterId to stalledPage.records[-1].Id.Change afterId to stalledPage.records[-1].Id.
ValuesChange morePages to true.Change morePages to true.
No
No steps
No
No steps
On error
Decisions & LoopsStop and report a problem: [Could not read your open opportunities from Salesforce, so nobody was messaged. Salesforce said: , salesforceError.message with the pattern ([^.!?])$ replaced by $1., Check the Salesforce connection in Lodol, then run the workflow again.] joined by nothing.Stop and report a problem: [Could not read your open opportunities from Salesforce, so nobody was messaged. Salesforce said: , salesforceError.message with the pattern ([^.!?])$ replaced by $1., Check the Salesforce connection in Lodol, then run the workflow again.] joined by nothing.
ValuesAdd 1 to pagesRead.Add 1 to pagesRead.
Decisions & LoopsIf morePages is yes and pagesRead is greater than or equal to 10If morePages is yes and pagesRead is greater than or equal to 10
Yes
ValuesChange readCapped to true.Change readCapped to true.
ValuesChange morePages to false.Change morePages to false.
No
No steps
ListsCount the items in stalledDeals and save it as stalledCount.Count the items in stalledDeals and save it as stalledCount.
Decisions & LoopsIf stalledCount is 0If stalledCount is 0
Yes
Decisions & LoopsFinish the run: No open opportunity has gone daysIdle days or more without activity or a stage change, so nobody was messaged.Finish the run: No open opportunity has gone daysIdle days or more without activity or a stage change, so nobody was messaged.
No
No steps
ValuesSet alreadySent to an empty list.Set alreadySent to an empty list.
Decisions & LoopsIf a step below fails, save the error as logErrorIf a step below fails, save the error as logError
Try
Stored ValuesGet the stored value 'stalled_deal_nudges'. Save it as nudgeLog.Get the stored value 'stalled_deal_nudges'. Save it as nudgeLog.
Decisions & LoopsIf nudgeLog.found is yesIf nudgeLog.found is yes
Yes
ListsKeep each item in nudgeLog.value where item starts with today and save it as alreadySent.Keep each item in nudgeLog.value where item starts with today and save it as alreadySent.
No
No steps
On error
Decisions & LoopsStop and report a problem: Could not check who has already been sent today's list, so nobody was messaged rather than risk sending someone a second copy. Run the workflow again in a few minutes.Stop and report a problem: Could not check who has already been sent today's list, so nobody was messaged rather than risk sending someone a second copy. Run the workflow again in a few minutes.
ListsGet Amount from every item in stalledDeals and save it as dealAmounts.Get Amount from every item in stalledDeals and save it as dealAmounts.
MathAdd up dealAmounts and save it as stalledValue.Add up dealAmounts and save it as stalledValue.
MathFormat stalledValue as a currency with 0 decimal places and save it as stalledValueText.Format stalledValue as a currency with 0 decimal places and save it as stalledValueText.
TextBuild the text , worth @stalledValueText and save it as summaryValueNote.Build the text , worth @stalledValueText and save it as summaryValueNote.
Decisions & LoopsIf stalledValue is 0If stalledValue is 0
Yes
ValuesChange summaryValueNote to blank.Change summaryValueNote to blank.
No
No steps
ListsGroup the items in stalledDeals by Owner.Email, with the total Amount of each and save it as repGroups.Group the items in stalledDeals by Owner.Email, with the total Amount of each and save it as repGroups.
ListsSort repGroups by total, largest first and save it as repsByValue.Sort repGroups by total, largest first and save it as repsByValue.
ValuesSet repsMessaged to an empty list.Set repsMessaged to an empty list.
ValuesSet repsAlreadySent to 0.Set repsAlreadySent to 0.
ValuesSet unreachedReps to an empty list.Set unreachedReps to an empty list.
ValuesSet inactiveOwners to an empty list.Set inactiveOwners to an empty list.
ValuesSet unrecorded to an empty list.Set unrecorded to an empty list.
ValuesSet managerLines to an empty list.Set managerLines to an empty list.
Decisions & LoopsFor each rep in repsByValue:For each rep in repsByValue:
ListsSort rep.items by Amount, largest first and save it as repDeals.Sort rep.items by Amount, largest first and save it as repDeals.
ValuesSet repName to repDeals[0].Owner.Name.Set repName to repDeals[0].Owner.Name.
TextMake rep.key lowercase and save it as repEmail.Make rep.key lowercase and save it as repEmail.
TextBuild the text @today @repEmail and save it as sentKey.Build the text @today @repEmail and save it as sentKey.
MathFormat rep.total as a currency with 0 decimal places and save it as repValue.Format rep.total as a currency with 0 decimal places and save it as repValue.
ValuesSet dealWord to deals.Set dealWord to deals.
ValuesSet verbWord to have.Set verbWord to have.
Decisions & LoopsIf rep.count is 1If rep.count is 1
Yes
ValuesChange dealWord to deal.Change dealWord to deal.
ValuesChange verbWord to has.Change verbWord to has.
No
No steps
ValuesSet repNote to blank.Set repNote to blank.
Decisions & LoopsIf repEmail is blankIf repEmail is blank
Yes
ValuesChange repName to Owner with no email address in Salesforce.Change repName to Owner with no email address in Salesforce.
ValuesChange repNote to (nobody to message).Change repNote to (nobody to message).
ListsAdd rep.count dealWord whose owner has no email address Salesforce would return to the end of unreachedReps and save it as unreachedReps.Add rep.count dealWord whose owner has no email address Salesforce would return to the end of unreachedReps and save it as unreachedReps.
Else if @repDeals[0].Owner.IsActive is no
ValuesChange repNote to (no longer active in Salesforce, so nobody was messaged).Change repNote to (no longer active in Salesforce, so nobody was messaged).
ListsAdd repName to the end of inactiveOwners and save it as inactiveOwners.Add repName to the end of inactiveOwners and save it as inactiveOwners.
Else if @alreadySent contains @sentKey is yes
ValuesAdd 1 to repsAlreadySent.Add 1 to repsAlreadySent.
Otherwise
ValuesSet dealLines to an empty list.Set dealLines to an empty list.
ListsTake the first maxDealsPerMessage items of repDeals and save it as listedDeals.Take the first maxDealsPerMessage items of repDeals and save it as listedDeals.
Decisions & LoopsFor each deal in listedDeals:For each deal in listedDeals:
Text Use deal.LastStageChangeDate, or deal.CreatedDate if it is empty and save it as stageMoved. Use deal.LastStageChangeDate, or deal.CreatedDate if it is empty and save it as stageMoved.
Dates & Times Make stageMoved readable as “2026-11-02” and save it as lastTouched. Make stageMoved readable as “2026-11-02” and save it as lastTouched.
Decisions & Loops If deal.LastActivityDate is greater than lastTouched If deal.LastActivityDate is greater than lastTouched
Yes
ValuesChange lastTouched to deal.LastActivityDate.Change lastTouched to deal.LastActivityDate.
No
No steps
Dates & Times Count the days from lastTouched to today and save it as idleFor. Count the days from lastTouched to today and save it as idleFor.
Values Set dealAmount to no amount. Set dealAmount to no amount.
Decisions & Loops If deal.Amount isn't empty If deal.Amount isn't empty
Yes
MathFormat deal.Amount as a currency with 0 decimal places and save it as dealAmount.Format deal.Amount as a currency with 0 decimal places and save it as dealAmount.
No
No steps
Dates & Times Make deal.CloseDate readable as “Nov 2, 2026” and save it as closeDay. Make deal.CloseDate readable as “Nov 2, 2026” and save it as closeDay.
Values Set closeNote to closes closeDay. Set closeNote to closes closeDay.
Decisions & Loops If deal.CloseDate is less than today If deal.CloseDate is less than today
Yes
TextBuild the text close date @closeDay has passed and save it as closeNote.Build the text close date @closeDay has passed and save it as closeNote.
No
No steps
Text Use deal.Account.Name, or no account if it is empty and save it as accountName. Use deal.Account.Name, or no account if it is empty and save it as accountName.
Text Replace < with &lt; in deal.Name and save it as dealName. Replace < with &lt; in deal.Name and save it as dealName.
Text Replace > with &gt; in dealName and save it as dealName. Replace > with &gt; in dealName and save it as dealName.
Lists Add • <https://@salesforceHost/@deal.Id|@dealName> · accountName · dealAmount · deal.StageName · closeNote · idleFor days idle to the end of dealLines and save it as dealLines. Add • <https://@salesforceHost/@deal.Id|@dealName> · accountName · dealAmount · deal.StageName · closeNote · idleFor days idle to the end of dealLines and save it as dealLines.
TextJoin dealLines with a new line and save it as dealList.Join dealLines with a new line and save it as dealList.
ValuesSet moreNote to blank.Set moreNote to blank.
Decisions & LoopsIf rep.count is greater than maxDealsPerMessageIf rep.count is greater than maxDealsPerMessage
Yes
MathSet unlistedCount to rep.count minus maxDealsPerMessage.Set unlistedCount to rep.count minus maxDealsPerMessage.
TextBuild the text _Plus @unlistedCount more not shown here, smaller or without an amount._ and save it as moreNote.Build the text _Plus @unlistedCount more not shown here, smaller or without an amount._ and save it as moreNote.
No
No steps
TextBuild the text , worth @repValue and save it as valueNote.Build the text , worth @repValue and save it as valueNote.
Decisions & LoopsIf rep.total is 0If rep.total is 0
Yes
ValuesChange valueNote to blank.Change valueNote to blank.
No
No steps
Decisions & LoopsIf a step below fails, save the error as slackErrorIf a step below fails, save the error as slackError
Try
SlackSlackSend a direct message to repEmail. Save it as repDm.Send a direct message to repEmail. Save it as repDm.*rep.count of your deals verbWord gone quiet@valueNote* No logged activity and no stage change in Salesforce for daysIdle days or more. Biggest first: dealList@moreNote Log a call, email or meeting on a deal, or move it to its next stage, and it drops off this list. If a d...
ListsAdd repName to the end of repsMessaged and save it as repsMessaged.Add repName to the end of repsMessaged and save it as repsMessaged.
ListsAdd sentKey to the end of alreadySent and save it as alreadySent.Add sentKey to the end of alreadySent and save it as alreadySent.
Decisions & LoopsIf a step below fails, save the error as recordErrorIf a step below fails, save the error as recordError
Try
Stored ValuesSet the stored value 'stalled_deal_nudges' to alreadySent. Save it as sentRecorded.Set the stored value 'stalled_deal_nudges' to alreadySent. Save it as sentRecorded.
On error
ListsAdd repName to the end of unrecorded and save it as unrecorded.Add repName to the end of unrecorded and save it as unrecorded.
On error
ValuesChange repNote to (could not be messaged in Slack).Change repNote to (could not be messaged in Slack).
ListsAdd repName (repEmail): slackError.message to the end of unreachedReps and save it as unreachedReps.Add repName (repEmail): slackError.message to the end of unreachedReps and save it as unreachedReps.
ListsAdd • repName: rep.count dealWord, repValue@repNote to the end of managerLines and save it as managerLines.Add • repName: rep.count dealWord, repValue@repNote to the end of managerLines and save it as managerLines.
ValuesSet summaryTo to blank.Set summaryTo to blank.
ValuesSet summaryProblem to blank.Set summaryProblem to blank.
Decisions & LoopsIf managerEmail isn't blankIf managerEmail isn't blank
Yes
TextBuild the text @today summary to @managerEmail and save it as summaryKey.Build the text @today summary to @managerEmail and save it as summaryKey.
Decisions & LoopsIf alreadySent doesn't contain summaryKeyIf alreadySent doesn't contain summaryKey
Yes
TextJoin managerLines with a new line and save it as repList.Join managerLines with a new line and save it as repList.
ValuesSet summaryNotes to an empty list.Set summaryNotes to an empty list.
Decisions & LoopsIf unreachedReps isn't emptyIf unreachedReps isn't empty
Yes
TextJoin unreachedReps with a new line and save it as unreachedList.Join unreachedReps with a new line and save it as unreachedList.
ListsAdd *Not reached in Slack*, so they have not seen their list:Add *Not reached in Slack*, so they have not seen their list: unreachedList to the end of summaryNotes and save it as summaryNotes.
No
No steps
Decisions & LoopsIf inactiveOwners isn't emptyIf inactiveOwners isn't empty
Yes
TextJoin inactiveOwners with , and save it as inactiveList.Join inactiveOwners with , and save it as inactiveList.
ListsAdd *Still owned by people no longer active in Salesforce:* inactiveList. Reassign these deals so someone picks them up. to the end of summaryNotes and save it as summaryNotes.Add *Still owned by people no longer active in Salesforce:* inactiveList. Reassign these deals so someone picks them up. to the end of summaryNotes and save it as summaryNotes.
No
No steps
Decisions & LoopsIf readCapped is yesIf readCapped is yes
Yes
ListsAdd Salesforce had more than 20,000 stalled deals and only the first 20,000 were read, so these figures are not complete. to the end of summaryNotes and save it as summaryNotes.Add Salesforce had more than 20,000 stalled deals and only the first 20,000 were read, so these figures are not complete. to the end of summaryNotes and save it as summaryNotes.
No
No steps
TextJoin summaryNotes with a blank line and save it as notesText.Join summaryNotes with a blank line and save it as notesText.
Decisions & LoopsIf a step below fails, save the error as summaryErrorIf a step below fails, save the error as summaryError
Try
SlackSlackSend a direct message to managerEmail. Save it as summaryDm.Send a direct message to managerEmail. Save it as summaryDm.*Deals gone quiet: stalledCount@summaryValueNote* Open opportunities with no logged activity and no stage change in Salesforce for daysIdle days or more. Each owner below has been sent their own list in Slack unless it says otherwise. By owner, biggest first: repList notes...
ValuesChange summaryTo to managerEmail.Change summaryTo to managerEmail.
ListsAdd summaryKey to the end of alreadySent and save it as alreadySent.Add summaryKey to the end of alreadySent and save it as alreadySent.
Decisions & LoopsIf a step below fails, save the error as summaryRecordErrorIf a step below fails, save the error as summaryRecordError
Try
Stored ValuesSet the stored value 'stalled_deal_nudges' to alreadySent. Save it as sentRecorded.Set the stored value 'stalled_deal_nudges' to alreadySent. Save it as sentRecorded.
On error
ListsAdd the manager's summary to the end of unrecorded and save it as unrecorded.Add the manager's summary to the end of unrecorded and save it as unrecorded.
On error
TextBuild the text The summary could not be sent to @managerEmail: @summaryError.message and save it as summaryProblem.Build the text The summary could not be sent to @managerEmail: @summaryError.message and save it as summaryProblem.
No
No steps
No
No steps
ValuesSet runNotes to an empty list.Set runNotes to an empty list.
ListsCount the items in repsMessaged and save it as messagedCount.Count the items in repsMessaged and save it as messagedCount.
Decisions & LoopsIf messagedCount is greater than 0If messagedCount is greater than 0
Yes
TextJoin repsMessaged with , and save it as messagedList.Join repsMessaged with , and save it as messagedList.
ListsAdd Sent messagedCount rep(s) their list: messagedList. to the end of runNotes and save it as runNotes.Add Sent messagedCount rep(s) their list: messagedList. to the end of runNotes and save it as runNotes.
No
No steps
Decisions & LoopsIf repsAlreadySent is greater than 0If repsAlreadySent is greater than 0
Yes
ListsAdd repsAlreadySent rep(s) had already been sent today's list, so it was not sent again. to the end of runNotes and save it as runNotes.Add repsAlreadySent rep(s) had already been sent today's list, so it was not sent again. to the end of runNotes and save it as runNotes.
No
No steps
Decisions & LoopsIf summaryTo isn't blankIf summaryTo isn't blank
Yes
ListsAdd Sent the summary to summaryTo. to the end of runNotes and save it as runNotes.Add Sent the summary to summaryTo. to the end of runNotes and save it as runNotes.
No
No steps
Decisions & LoopsIf inactiveOwners isn't emptyIf inactiveOwners isn't empty
Yes
TextJoin inactiveOwners with , and save it as inactiveNames.Join inactiveOwners with , and save it as inactiveNames.
ListsAdd Not messaged because they are no longer active in Salesforce: inactiveNames. Reassign their deals. to the end of runNotes and save it as runNotes.Add Not messaged because they are no longer active in Salesforce: inactiveNames. Reassign their deals. to the end of runNotes and save it as runNotes.
No
No steps
ValuesSet problems to an empty list.Set problems to an empty list.
Decisions & LoopsIf unreachedReps isn't emptyIf unreachedReps isn't empty
Yes
TextJoin unreachedReps with ; and save it as unreachedText.Join unreachedReps with ; and save it as unreachedText.
ListsAdd Could not message in Slack: unreachedText. Check that their Slack email matches the one in Salesforce. to the end of problems and save it as problems.Add Could not message in Slack: unreachedText. Check that their Slack email matches the one in Salesforce. to the end of problems and save it as problems.
No
No steps
Decisions & LoopsIf summaryProblem isn't blankIf summaryProblem isn't blank
Yes
ListsAdd summaryProblem. to the end of problems and save it as problems.Add summaryProblem. to the end of problems and save it as problems.
No
No steps
Decisions & LoopsIf unrecorded isn't emptyIf unrecorded isn't empty
Yes
TextJoin unrecorded with , and save it as unrecordedText.Join unrecorded with , and save it as unrecordedText.
ListsAdd Sent, but could not note it as sent, so running this again today would send it a second time: unrecordedText. to the end of problems and save it as problems.Add Sent, but could not note it as sent, so running this again today would send it a second time: unrecordedText. to the end of problems and save it as problems.
No
No steps
Decisions & LoopsIf readCapped is yesIf readCapped is yes
Yes
ListsAdd Salesforce had more than 20,000 stalled deals; only the first 20,000 were read, so some reps may be missing deals. Raise 'daysIdle' to narrow the list. to the end of problems and save it as problems.Add Salesforce had more than 20,000 stalled deals; only the first 20,000 were read, so some reps may be missing deals. Raise 'daysIdle' to narrow the list. to the end of problems and save it as problems.
No
No steps
TextBuild the text Found @stalledCount open deal(s) worth @stalledValueText with no activity or stage change for @daysIdle days or more. and save it as runSummary.Build the text Found @stalledCount open deal(s) worth @stalledValueText with no activity or stage change for @daysIdle days or more. and save it as runSummary.
TextJoin runNotes with a space and save it as notesLine.Join runNotes with a space and save it as notesLine.
Decisions & LoopsIf problems isn't emptyIf problems isn't empty
Yes
TextJoin problems with a space and save it as problemsLine.Join problems with a space and save it as problemsLine.
Decisions & LoopsStop and report a problem: runSummary notesLine problemsLine with the pattern (?<!\.)\.\.(?!\.) replaced by . with the pattern {2,} replaced by .Stop and report a problem: runSummary notesLine problemsLine with the pattern (?<!\.)\.\.(?!\.) replaced by . with the pattern {2,} replaced by .
No
No steps
Decisions & LoopsFinish the run: runSummary notesLine with the pattern (?<!\.)\.\.(?!\.) replaced by . with the pattern {2,} replaced by .Finish the run: runSummary notesLine with the pattern (?<!\.)\.\.(?!\.) replaced by . with the pattern {2,} replaced by .